FPS Boosts (45 > 120 on my chromebook), FPS Counter, QoL updates, and Custom crosshair
// ==UserScript==
// @name Krunker+
// @namespace https://greasyfork.org/en/users/1573232-rhenryw
// @version 2.3
// @description FPS Boosts (45 > 120 on my chromebook), FPS Counter, QoL updates, and Custom crosshair
// @author RHW
// @match *://krunker.io/*
// @match *://*.krunker.io/*
// @grant none
// @run-at document-start
// @license AGPLv3
// ==/UserScript==
(function() {
'use strict';
const CONFIG = {
crosshair: {
enabled: true,
style: 'dot',
color: '#00ff00',
size: 8,
thickness: 2,
gap: 4,
outlineColor: '#000000',
outlineWidth: 1,
opacity: 1,
customImage: null,
customImageSize: 32
},
fps: {
enabled: true,
showGraph: true,
position: 'top-right',
color: '#00ff00',
showAlways: true
},
performance: {
maxFps: 999,
reduceShadows: true,
reduceParticles: true,
reduceReflections: true,
reducePostProcessing: true,
lowResTextures: true,
disableGrass: true,
disableFog: true,
reduceDrawDistance: true
},
gameplay: {
hitMarkers: true,
hitMarkerColor: '#ffffff',
damageIndicators: true,
playerOutlines: true,
tracerRounds: true,
autoPickup: true,
quickScope: true
},
ui: {
darkMode: true,
hideAds: true,
menuKey: 'F1'
}
};
let lastFrameTime = performance.now();
let frameCount = 0;
let fps = 0;
let fpsHistory = [];
const maxFpsHistory = 60;
let crosshairElement = null;
let settingsPanel = null;
const StyleCSS = document.createElement('style');
StyleCSS.id = 'enhancer-styles';
StyleCSS.textContent = `
.enhancer-fps-counter {
position: fixed;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.8);
color: var(--fps-color, #00ff00);
padding: 8px 12px;
border-radius: 6px;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 16px;
font-weight: bold;
z-index: 2147483647;
border: 1px solid rgba(0, 255, 0, 0.3);
text-shadow: 0 0 10px var(--fps-color, #00ff00);
min-width: 90px;
text-align: center;
}
.enhancer-fps-graph {
position: fixed;
top: 50px;
right: 10px;
width: 120px;
height: 40px;
background: rgba(0, 0, 0, 0.7);
border-radius: 4px;
z-index: 2147483646;
overflow: hidden;
}
.enhancer-fps-graph canvas {
width: 100%;
height: 100%;
}
.enhancer-crosshair {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
opacity: var(--crosshair-opacity, 1);
}
.enhancer-crosshair-image {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.enhancer-hitmarker {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 30px;
height: 30px;
pointer-events: none;
z-index: 2147483645;
opacity: 0;
transition: opacity 0.1s;
}
.enhancer-hitmarker.show {
opacity: 1;
}
.enhancer-hitmarker::before,
.enhancer-hitmarker::after {
content: '';
position: absolute;
background: var(--hitmarker-color, #fff);
box-shadow: 0 0 6px var(--hitmarker-color, #fff);
}
.enhancer-hitmarker::before {
width: 2px;
height: 12px;
left: 14px;
top: 0;
transform: rotate(45deg);
}
.enhancer-hitmarker::after {
width: 2px;
height: 12px;
left: 14px;
bottom: 0;
transform: rotate(-45deg);
}
.enhancer-damage-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 2147483644;
border: 0 solid rgba(255, 0, 0, 0);
transition: border-width 0.1s, border-color 0.1s;
}
.enhancer-damage-overlay.hit {
border-width: 20px;
border-color: rgba(255, 0, 0, 0.3);
}
.enhancer-settings-btn {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
z-index: 2147483647;
font-family: 'Segoe UI', sans-serif;
font-size: 12px;
transition: all 0.2s;
}
.enhancer-settings-btn:hover {
background: rgba(50, 50, 50, 0.9);
border-color: rgba(255, 255, 255, 0.4);
}
.enhancer-settings-panel {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(20, 20, 30, 0.98);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 12px;
padding: 25px;
width: 400px;
max-height: 80vh;
overflow-y: auto;
z-index: 2147483647;
color: #fff;
font-family: 'Segoe UI', sans-serif;
display: none;
box-shadow: 0 10px 50px rgba(0, 0, 0, 0.7);
}
.enhancer-settings-panel.show {
display: block;
}
.enhancer-settings-title {
font-size: 20px;
font-weight: bold;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
display: flex;
justify-content: space-between;
align-items: center;
}
.enhancer-settings-section {
margin: 18px 0;
padding: 12px;
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.enhancer-settings-section-title {
font-size: 14px;
color: #00ff00;
margin-bottom: 12px;
font-weight: bold;
}
.enhancer-settings-row {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
padding: 8px 0;
}
.enhancer-settings-label {
font-size: 13px;
color: #ccc;
}
.enhancer-toggle {
width: 44px;
height: 22px;
background: rgba(255, 255, 255, 0.15);
border-radius: 11px;
position: relative;
cursor: pointer;
transition: background 0.2s;
}
.enhancer-toggle.active {
background: #00cc00;
}
.enhancer-toggle::after {
content: '';
position: absolute;
width: 18px;
height: 18px;
background: #fff;
border-radius: 50%;
top: 2px;
left: 2px;
transition: left 0.2s;
}
.enhancer-toggle.active::after {
left: 24px;
}
.enhancer-close-btn {
background: none;
border: none;
color: #888;
font-size: 24px;
cursor: pointer;
padding: 0 8px;
}
.enhancer-close-btn:hover {
color: #ff4444;
}
.enhancer-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 2147483646;
display: none;
}
.enhancer-overlay.show {
display: block;
}
body.enhancer-dark {
background-color: #111 !important;
}
body.enhancer-dark #gameCanvas {
filter: brightness(1.05) contrast(1.02);
}
.enhancer-color-picker {
width: 50px;
height: 30px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
cursor: pointer;
background: none;
padding: 0;
}
.enhancer-color-picker::-webkit-color-swatch-wrapper {
padding: 2px;
}
.enhancer-color-picker::-webkit-color-swatch {
border: none;
border-radius: 2px;
}
.enhancer-slider {
width: 120px;
height: 6px;
-webkit-appearance: none;
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
outline: none;
}
.enhancer-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: #00ff00;
border-radius: 50%;
cursor: pointer;
}
.enhancer-slider-value {
min-width: 35px;
text-align: right;
font-size: 12px;
color: #888;
}
.enhancer-select {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff;
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
}
.enhancer-select option {
background: #222;
}
.enhancer-dropzone {
width: 100%;
height: 80px;
border: 2px dashed rgba(255, 255, 255, 0.3);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: #888;
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
margin-top: 10px;
}
.enhancer-dropzone:hover, .enhancer-dropzone.dragover {
border-color: #00ff00;
color: #00ff00;
background: rgba(0, 255, 0, 0.05);
}
.enhancer-dropzone.has-image {
border-style: solid;
border-color: #00ff00;
}
.enhancer-crosshair-preview {
display: flex;
justify-content: center;
padding: 20px;
background: rgba(0, 0, 0, 0.4);
border-radius: 8px;
margin-top: 10px;
}
.enhancer-crosshair-preview-box {
position: relative;
width: 100px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
.enhancer-preview-crosshair {
position: relative;
}
.enhancer-btn {
background: rgba(0, 255, 0, 0.2);
border: 1px solid rgba(0, 255, 0, 0.4);
color: #00ff00;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
}
.enhancer-btn:hover {
background: rgba(0, 255, 0, 0.3);
border-color: #00ff00;
}
.enhancer-btn-danger {
background: rgba(255, 0, 0, 0.2);
border-color: rgba(255, 0, 0, 0.4);
color: #ff4444;
}
.enhancer-btn-danger:hover {
background: rgba(255, 0, 0, 0.3);
border-color: #ff4444;
}
.enhancer-row-group {
display: flex;
gap: 15px;
align-items: center;
}
`;
document.documentElement.appendChild(StyleCSS);
function createFPSCounter() {
const counter = document.createElement('div');
counter.id = 'enhancer-fps-counter';
counter.className = 'enhancer-fps-counter';
counter.style.setProperty('--fps-color', CONFIG.fps.color);
counter.innerHTML = '<span id="fps-value">--</span> FPS';
document.body.appendChild(counter);
if (CONFIG.fps.showGraph) {
const graphContainer = document.createElement('div');
graphContainer.className = 'enhancer-fps-graph';
const canvas = document.createElement('canvas');
canvas.id = 'enhancer-fps-canvas';
canvas.width = 120;
canvas.height = 40;
graphContainer.appendChild(canvas);
document.body.appendChild(graphContainer);
}
}
function updateFPS() {
frameCount++;
const now = performance.now();
const delta = now - lastFrameTime;
if (delta >= 1000) {
fps = Math.round((frameCount * 1000) / delta);
frameCount = 0;
lastFrameTime = now;
fpsHistory.push(fps);
if (fpsHistory.length > maxFpsHistory) fpsHistory.shift();
const fpsEl = document.getElementById('fps-value');
if (fpsEl) {
fpsEl.textContent = fps;
}
if (CONFIG.fps.showGraph) {
drawFPSGraph();
}
}
requestAnimationFrame(updateFPS);
}
function drawFPSGraph() {
const canvas = document.getElementById('enhancer-fps-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (fpsHistory.length < 2) return;
ctx.beginPath();
ctx.strokeStyle = CONFIG.fps.color;
ctx.lineWidth = 1.5;
const maxFps = Math.max(...fpsHistory, 120);
const stepX = canvas.width / (maxFpsHistory - 1);
fpsHistory.forEach((f, i) => {
const x = i * stepX;
const y = canvas.height - (f / maxFps) * canvas.height;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
ctx.fillStyle = CONFIG.fps.color + '20';
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.fill();
}
function createCustomCrosshair() {
if (!CONFIG.crosshair.enabled) {
if (crosshairElement) crosshairElement.style.display = 'none';
return;
}
if (!crosshairElement) {
crosshairElement = document.createElement('div');
crosshairElement.id = 'enhancer-crosshair';
crosshairElement.className = 'enhancer-crosshair';
document.body.appendChild(crosshairElement);
}
crosshairElement.style.display = 'block';
crosshairElement.style.opacity = CONFIG.crosshair.opacity;
crosshairElement.style.zIndex = '2147483647';
if (CONFIG.crosshair.customImage) {
crosshairElement.className = 'enhancer-crosshair enhancer-crosshair-image';
crosshairElement.style.width = CONFIG.crosshair.customImageSize + 'px';
crosshairElement.style.height = CONFIG.crosshair.customImageSize + 'px';
crosshairElement.style.backgroundImage = `url(${CONFIG.crosshair.customImage})`;
crosshairElement.style.background = `url(${CONFIG.crosshair.customImage}) center/contain no-repeat`;
crosshairElement.innerHTML = '';
return;
}
crosshairElement.style.backgroundImage = '';
crosshairElement.style.width = '';
crosshairElement.style.height = '';
const color = CONFIG.crosshair.color;
const size = CONFIG.crosshair.size;
const thickness = CONFIG.crosshair.thickness;
const gap = CONFIG.crosshair.gap;
const outline = CONFIG.crosshair.outlineWidth > 0;
const outlineColor = CONFIG.crosshair.outlineColor;
const outlineWidth = CONFIG.crosshair.outlineWidth;
let crosshairHTML = '';
switch (CONFIG.crosshair.style) {
case 'dot':
crosshairElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
width: ${size}px;
height: ${size}px;
background: ${color};
border-radius: 50%;
${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor}, 0 0 ${thickness * 2}px ${color};` : `box-shadow: 0 0 ${thickness * 2}px ${color};`}
opacity: ${CONFIG.crosshair.opacity};
`;
crosshairElement.innerHTML = '';
break;
case 'cross':
crosshairElement.innerHTML = `
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
<div style="position: absolute; left: 50%; top: -${size + gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
</div>
`;
crosshairElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
opacity: ${CONFIG.crosshair.opacity};
`;
break;
case 'circle':
crosshairElement.innerHTML = '';
crosshairElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
width: ${size}px;
height: ${size}px;
border: ${thickness}px solid ${color};
border-radius: 50%;
${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor}, 0 0 ${thickness}px ${color};` : `box-shadow: 0 0 ${thickness}px ${color};`}
opacity: ${CONFIG.crosshair.opacity};
background: transparent;
`;
break;
case 'tcross':
crosshairElement.innerHTML = `
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
</div>
`;
crosshairElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
opacity: ${CONFIG.crosshair.opacity};
`;
break;
case 'xhair':
crosshairElement.innerHTML = `
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
<div style="position: absolute; left: 50%; top: -${size + gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: ${size/2}px; height: ${size/2}px; background: ${color}; border-radius: 50%; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
</div>
`;
crosshairElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 2147483647;
opacity: ${CONFIG.crosshair.opacity};
`;
break;
}
}
function createHitmarker() {
const hitmarker = document.createElement('div');
hitmarker.id = 'enhancer-hitmarker';
hitmarker.className = 'enhancer-hitmarker';
hitmarker.style.setProperty('--hitmarker-color', CONFIG.gameplay.hitMarkerColor);
document.body.appendChild(hitmarker);
}
function showHitmarker() {
const hitmarker = document.getElementById('enhancer-hitmarker');
if (!hitmarker) return;
hitmarker.classList.add('show');
setTimeout(() => hitmarker.classList.remove('show'), 150);
}
function createDamageOverlay() {
const overlay = document.createElement('div');
overlay.id = 'enhancer-damage-overlay';
overlay.className = 'enhancer-damage-overlay';
document.body.appendChild(overlay);
}
function showDamageOverlay() {
const overlay = document.getElementById('enhancer-damage-overlay');
if (!overlay) return;
overlay.classList.add('hit');
setTimeout(() => overlay.classList.remove('hit'), 200);
}
function createSettingsPanel() {
const overlay = document.createElement('div');
overlay.id = 'enhancer-overlay';
overlay.className = 'enhancer-overlay';
const panel = document.createElement('div');
panel.id = 'enhancer-settings-panel';
panel.className = 'enhancer-settings-panel';
settingsPanel = panel;
updateSettingsPanel();
document.body.appendChild(overlay);
document.body.appendChild(panel);
const btn = document.createElement('button');
btn.className = 'enhancer-settings-btn';
btn.textContent = '⚙ Enhancer';
btn.onclick = () => {
panel.classList.add('show');
overlay.classList.add('show');
updateSettingsPanel();
};
document.body.appendChild(btn);
overlay.onclick = () => {
panel.classList.remove('show');
overlay.classList.remove('show');
};
document.addEventListener('keydown', (e) => {
if (e.key === CONFIG.ui.menuKey && !e.repeat) {
panel.classList.toggle('show');
overlay.classList.toggle('show');
if (panel.classList.contains('show')) {
updateSettingsPanel();
}
}
if (e.key === 'Escape' && panel.classList.contains('show')) {
panel.classList.remove('show');
overlay.classList.remove('show');
}
});
}
function updateSettingsPanel() {
if (!settingsPanel) return;
settingsPanel.innerHTML = `
<div class="enhancer-settings-title">
<span>Enhancer Settings</span>
<button class="enhancer-close-btn">×</button>
</div>
<div class="enhancer-settings-section">
<div class="enhancer-settings-section-title">Crosshair</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Enabled</span>
<div class="enhancer-toggle ${CONFIG.crosshair.enabled ? 'active' : ''}" data-config="crosshair.enabled"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Style</span>
<select class="enhancer-select" data-config="crosshair.style">
<option value="dot" ${CONFIG.crosshair.style === 'dot' ? 'selected' : ''}>Dot</option>
<option value="cross" ${CONFIG.crosshair.style === 'cross' ? 'selected' : ''}>Cross</option>
<option value="circle" ${CONFIG.crosshair.style === 'circle' ? 'selected' : ''}>Circle</option>
<option value="tcross" ${CONFIG.crosshair.style === 'tcross' ? 'selected' : ''}>T-Cross</option>
<option value="xhair" ${CONFIG.crosshair.style === 'xhair' ? 'selected' : ''}>Cross + Dot</option>
</select>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Color</span>
<input type="color" class="enhancer-color-picker" data-config="crosshair.color" value="${CONFIG.crosshair.color}">
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Outline Color</span>
<input type="color" class="enhancer-color-picker" data-config="crosshair.outlineColor" value="${CONFIG.crosshair.outlineColor}">
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Size</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.size" min="2" max="40" value="${CONFIG.crosshair.size}">
<span class="enhancer-slider-value">${CONFIG.crosshair.size}px</span>
</div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Thickness</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.thickness" min="1" max="10" value="${CONFIG.crosshair.thickness}">
<span class="enhancer-slider-value">${CONFIG.crosshair.thickness}px</span>
</div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Gap</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.gap" min="0" max="20" value="${CONFIG.crosshair.gap}">
<span class="enhancer-slider-value">${CONFIG.crosshair.gap}px</span>
</div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Outline Width</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.outlineWidth" min="0" max="5" value="${CONFIG.crosshair.outlineWidth}">
<span class="enhancer-slider-value">${CONFIG.crosshair.outlineWidth}px</span>
</div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Opacity</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.opacity" min="0.1" max="1" step="0.1" value="${CONFIG.crosshair.opacity}">
<span class="enhancer-slider-value">${Math.round(CONFIG.crosshair.opacity * 100)}%</span>
</div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Custom Image</span>
<button class="enhancer-btn ${CONFIG.crosshair.customImage ? 'enhancer-btn-danger' : ''}" id="clearCustomImage">${CONFIG.crosshair.customImage ? 'Clear Image' : 'None'}</button>
</div>
<div class="enhancer-dropzone" id="crosshairDropzone">
${CONFIG.crosshair.customImage ? '✓ Custom image loaded' : 'Drop PNG image here or click to upload'}
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Image Size</span>
<div class="enhancer-row-group">
<input type="range" class="enhancer-slider" data-config="crosshair.customImageSize" min="16" max="128" value="${CONFIG.crosshair.customImageSize}">
<span class="enhancer-slider-value">${CONFIG.crosshair.customImageSize}px</span>
</div>
</div>
<div class="enhancer-crosshair-preview">
<div class="enhancer-crosshair-preview-box" id="crosshairPreview"></div>
</div>
</div>
<div class="enhancer-settings-section">
<div class="enhancer-settings-section-title">FPS Display</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Show FPS</span>
<div class="enhancer-toggle ${CONFIG.fps.enabled ? 'active' : ''}" data-config="fps.enabled"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Show Graph</span>
<div class="enhancer-toggle ${CONFIG.fps.showGraph ? 'active' : ''}" data-config="fps.showGraph"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Color</span>
<input type="color" class="enhancer-color-picker" data-config="fps.color" value="${CONFIG.fps.color}">
</div>
</div>
<div class="enhancer-settings-section">
<div class="enhancer-settings-section-title">Performance</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Reduce Shadows</span>
<div class="enhancer-toggle ${CONFIG.performance.reduceShadows ? 'active' : ''}" data-config="performance.reduceShadows"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Reduce Particles</span>
<div class="enhancer-toggle ${CONFIG.performance.reduceParticles ? 'active' : ''}" data-config="performance.reduceParticles"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Low Res Textures</span>
<div class="enhancer-toggle ${CONFIG.performance.lowResTextures ? 'active' : ''}" data-config="performance.lowResTextures"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Disable Grass</span>
<div class="enhancer-toggle ${CONFIG.performance.disableGrass ? 'active' : ''}" data-config="performance.disableGrass"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Disable Fog</span>
<div class="enhancer-toggle ${CONFIG.performance.disableFog ? 'active' : ''}" data-config="performance.disableFog"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Reduce Draw Distance</span>
<div class="enhancer-toggle ${CONFIG.performance.reduceDrawDistance ? 'active' : ''}" data-config="performance.reduceDrawDistance"></div>
</div>
</div>
<div class="enhancer-settings-section">
<div class="enhancer-settings-section-title">Gameplay</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Hit Markers</span>
<div class="enhancer-toggle ${CONFIG.gameplay.hitMarkers ? 'active' : ''}" data-config="gameplay.hitMarkers"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Hit Marker Color</span>
<input type="color" class="enhancer-color-picker" data-config="gameplay.hitMarkerColor" value="${CONFIG.gameplay.hitMarkerColor}">
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Damage Indicators</span>
<div class="enhancer-toggle ${CONFIG.gameplay.damageIndicators ? 'active' : ''}" data-config="gameplay.damageIndicators"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Auto Pickup</span>
<div class="enhancer-toggle ${CONFIG.gameplay.autoPickup ? 'active' : ''}" data-config="gameplay.autoPickup"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Quick Scope</span>
<div class="enhancer-toggle ${CONFIG.gameplay.quickScope ? 'active' : ''}" data-config="gameplay.quickScope"></div>
</div>
</div>
<div class="enhancer-settings-section">
<div class="enhancer-settings-section-title">UI</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Dark Mode</span>
<div class="enhancer-toggle ${CONFIG.ui.darkMode ? 'active' : ''}" data-config="ui.darkMode"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Hide Ads</span>
<div class="enhancer-toggle ${CONFIG.ui.hideAds ? 'active' : ''}" data-config="ui.hideAds"></div>
</div>
<div class="enhancer-settings-row">
<span class="enhancer-settings-label">Menu Key</span>
<select class="enhancer-select" data-config="ui.menuKey">
<option value="F1" ${CONFIG.ui.menuKey === 'F1' ? 'selected' : ''}>F1</option>
<option value="F2" ${CONFIG.ui.menuKey === 'F2' ? 'selected' : ''}>F2</option>
<option value="F3" ${CONFIG.ui.menuKey === 'F3' ? 'selected' : ''}>F3</option>
<option value="F4" ${CONFIG.ui.menuKey === 'F4' ? 'selected' : ''}>F4</option>
<option value="Insert" ${CONFIG.ui.menuKey === 'Insert' ? 'selected' : ''}>Insert</option>
</select>
</div>
</div>
`;
settingsPanel.querySelector('.enhancer-close-btn').onclick = () => {
settingsPanel.classList.remove('show');
document.getElementById('enhancer-overlay').classList.remove('show');
};
settingsPanel.querySelectorAll('.enhancer-toggle').forEach(toggle => {
toggle.onclick = () => {
const configPath = toggle.dataset.config;
setConfigValue(configPath, !getConfigValue(configPath));
toggle.classList.toggle('active');
applySettings();
saveConfig();
};
});
settingsPanel.querySelectorAll('.enhancer-select').forEach(select => {
select.onchange = () => {
setConfigValue(select.dataset.config, select.value);
applySettings();
saveConfig();
};
});
settingsPanel.querySelectorAll('.enhancer-color-picker').forEach(picker => {
picker.oninput = () => {
setConfigValue(picker.dataset.config, picker.value);
applySettings();
saveConfig();
};
});
settingsPanel.querySelectorAll('.enhancer-slider').forEach(slider => {
slider.oninput = () => {
const value = parseFloat(slider.value);
setConfigValue(slider.dataset.config, value);
slider.parentElement.querySelector('.enhancer-slider-value').textContent =
slider.dataset.config.includes('opacity') ? Math.round(value * 100) + '%' : value + 'px';
applySettings();
saveConfig();
};
});
const dropzone = settingsPanel.querySelector('#crosshairDropzone');
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = 'image/png';
fileInput.style.display = 'none';
dropzone.onclick = () => fileInput.click();
dropzone.ondragover = (e) => {
e.preventDefault();
dropzone.classList.add('dragover');
};
dropzone.ondragleave = () => {
dropzone.classList.remove('dragover');
};
dropzone.ondrop = (e) => {
e.preventDefault();
dropzone.classList.remove('dragover');
const file = e.dataTransfer.files[0];
if (file && file.type === 'image/png') {
loadCustomCrosshairImage(file);
}
};
fileInput.onchange = (e) => {
const file = e.target.files[0];
if (file && file.type === 'image/png') {
loadCustomCrosshairImage(file);
}
};
settingsPanel.appendChild(fileInput);
settingsPanel.querySelector('#clearCustomImage').onclick = () => {
if (CONFIG.crosshair.customImage) {
CONFIG.crosshair.customImage = null;
dropzone.textContent = 'Drop PNG image here or click to upload';
dropzone.classList.remove('has-image');
settingsPanel.querySelector('#clearCustomImage').textContent = 'None';
settingsPanel.querySelector('#clearCustomImage').classList.remove('enhancer-btn-danger');
applySettings();
saveConfig();
}
};
updateCrosshairPreview();
}
function loadCustomCrosshairImage(file) {
const reader = new FileReader();
reader.onload = (e) => {
CONFIG.crosshair.customImage = e.target.result;
const dropzone = settingsPanel.querySelector('#crosshairDropzone');
dropzone.textContent = '✓ Custom image loaded';
dropzone.classList.add('has-image');
settingsPanel.querySelector('#clearCustomImage').textContent = 'Clear Image';
settingsPanel.querySelector('#clearCustomImage').classList.add('enhancer-btn-danger');
applySettings();
saveConfig();
};
reader.readAsDataURL(file);
}
function updateCrosshairPreview() {
const preview = document.getElementById('crosshairPreview');
if (!preview) return;
preview.innerHTML = '';
const previewCrosshair = document.createElement('div');
previewCrosshair.className = 'enhancer-preview-crosshair';
previewCrosshair.style.position = 'relative';
if (CONFIG.crosshair.customImage) {
previewCrosshair.style.width = CONFIG.crosshair.customImageSize + 'px';
previewCrosshair.style.height = CONFIG.crosshair.customImageSize + 'px';
previewCrosshair.style.background = `url(${CONFIG.crosshair.customImage}) center/contain no-repeat`;
} else {
const color = CONFIG.crosshair.color;
const size = CONFIG.crosshair.size;
const thickness = CONFIG.crosshair.thickness;
const gap = CONFIG.crosshair.gap;
const outline = CONFIG.crosshair.outlineWidth > 0;
const outlineColor = CONFIG.crosshair.outlineColor;
const outlineWidth = CONFIG.crosshair.outlineWidth;
switch (CONFIG.crosshair.style) {
case 'dot':
previewCrosshair.style.cssText += `width: ${size}px; height: ${size}px; background: ${color}; border-radius: 50%; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}`;
break;
case 'cross':
previewCrosshair.innerHTML = `
<div style="position: absolute; left: 50%; top: -${size + gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
`;
break;
case 'circle':
previewCrosshair.style.cssText += `width: ${size}px; height: ${size}px; border: ${thickness}px solid ${color}; border-radius: 50%; background: transparent; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}`;
break;
case 'tcross':
previewCrosshair.innerHTML = `
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
`;
break;
case 'xhair':
previewCrosshair.innerHTML = `
<div style="position: absolute; left: 50%; top: -${size + gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: ${gap}px; transform: translateX(-50%); width: ${thickness}px; height: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: -${size + gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; top: 50%; left: ${gap}px; transform: translateY(-50%); height: ${thickness}px; width: ${size}px; background: ${color}; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
<div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: ${size/2}px; height: ${size/2}px; background: ${color}; border-radius: 50%; ${outline ? `box-shadow: 0 0 0 ${outlineWidth}px ${outlineColor};` : ''}"></div>
`;
break;
}
}
previewCrosshair.style.opacity = CONFIG.crosshair.opacity;
preview.appendChild(previewCrosshair);
}
function getConfigValue(path) {
const keys = path.split('.');
let obj = CONFIG;
for (const key of keys) {
obj = obj[key];
}
return obj;
}
function setConfigValue(path, value) {
const keys = path.split('.');
let obj = CONFIG;
for (let i = 0; i < keys.length - 1; i++) {
obj = obj[keys[i]];
}
obj[keys[keys.length - 1]] = value;
}
function applySettings() {
const fpsCounter = document.getElementById('enhancer-fps-counter');
if (fpsCounter) {
fpsCounter.style.display = CONFIG.fps.enabled ? 'block' : 'none';
fpsCounter.style.setProperty('--fps-color', CONFIG.fps.color);
}
const fpsGraph = document.querySelector('.enhancer-fps-graph');
if (fpsGraph) {
fpsGraph.style.display = CONFIG.fps.showGraph ? 'block' : 'none';
}
const hitmarker = document.getElementById('enhancer-hitmarker');
if (hitmarker) {
hitmarker.style.setProperty('--hitmarker-color', CONFIG.gameplay.hitMarkerColor);
}
createCustomCrosshair();
updateCrosshairPreview();
applyPerformanceSettings();
}
function applyPerformanceSettings() {
if (CONFIG.ui.darkMode) {
document.body.classList.add('enhancer-dark');
} else {
document.body.classList.remove('enhancer-dark');
}
const perfCSS = document.getElementById('enhancer-perf-styles') || document.createElement('style');
perfCSS.id = 'enhancer-perf-styles';
let perfRules = '';
if (CONFIG.performance.disableGrass) {
perfRules += `.grass, [class*="grass"], [class*="Grass"] { display: none !important; }`;
}
if (CONFIG.performance.disableFog) {
perfRules += `.fog, [class*="fog"], [class*="Fog"] { display: none !important; }`;
}
if (CONFIG.ui.hideAds) {
perfRules += `#aHolder, #sponsorBlock, [id*="ad"], [class*="ad-"], [class*="ads-"] { display: none !important; }`;
}
perfCSS.textContent = perfRules;
if (!document.getElementById('enhancer-perf-styles')) {
document.head.appendChild(perfCSS);
}
optimizeGameSettings();
}
function optimizeGameSettings() {
const settings = {
highPerformance: true,
particleQuality: CONFIG.performance.reduceParticles ? 0 : 1,
shadowQuality: CONFIG.performance.reduceShadows ? 0 : 2,
reflectionQuality: CONFIG.performance.reduceReflections ? 0 : 2,
postProcessing: CONFIG.performance.reducePostProcessing ? false : true,
textureQuality: CONFIG.performance.lowResTextures ? 0 : 2,
viewDistance: CONFIG.performance.reduceDrawDistance ? 500 : 1000,
fpsCap: CONFIG.performance.maxFps,
vsync: false,
antiAliasing: 0,
ambientOcclusion: false,
bloom: false,
motionBlur: false,
depthOfField: false,
lensFlare: false,
grass: !CONFIG.performance.disableGrass,
fog: !CONFIG.performance.disableFog,
shaderQuality: 0,
waterQuality: 0
};
localStorage.setItem('krunker_settings', JSON.stringify(settings));
if (window.windows && window.windows.settings) {
try {
Object.keys(settings).forEach(key => {
if (window.windows.settings[key] !== undefined) {
window.windows.settings[key] = settings[key];
}
});
} catch (e) {}
}
if (window.game && window.game.scene) {
try {
const scene = window.game.scene;
if (scene.fog) scene.fog.enabled = !CONFIG.performance.disableFog;
scene.shadowsEnabled = !CONFIG.performance.reduceShadows;
} catch (e) {}
}
}
function hookGameEvents() {
const originalPostMessage = window.postMessage;
window.postMessage = function(message) {
if (typeof message === 'string') {
try {
const data = JSON.parse(message);
if (data.hurt || data.damage) {
if (CONFIG.gameplay.damageIndicators) {
showDamageOverlay();
}
}
if (data.hit || data.kill) {
if (CONFIG.gameplay.hitMarkers) {
showHitmarker();
}
}
} catch (e) {}
}
return originalPostMessage.apply(this, arguments);
};
document.addEventListener('keydown', (e) => {
if (e.key === 'F' && CONFIG.gameplay.autoPickup) {
const pickupBtn = document.querySelector('[class*="pickup"], [class*="interact"]');
if (pickupBtn) pickupBtn.click();
}
});
if (CONFIG.gameplay.quickScope) {
let scopeTimeout = null;
document.addEventListener('mousedown', (e) => {
if (e.button === 2) {
scopeTimeout = setTimeout(() => {
document.body.style.filter = 'brightness(0.7)';
}, 50);
}
});
document.addEventListener('mouseup', (e) => {
if (e.button === 2) {
clearTimeout(scopeTimeout);
document.body.style.filter = '';
}
});
}
}
function saveConfig() {
localStorage.setItem('enhancer_config', JSON.stringify(CONFIG));
}
function loadConfig() {
const saved = localStorage.getItem('enhancer_config');
if (saved) {
try {
const savedConfig = JSON.parse(saved);
deepMerge(CONFIG, savedConfig);
} catch (e) {}
}
}
function deepMerge(target, source) {
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
if (!target[key]) target[key] = {};
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
function init() {
loadConfig();
if (CONFIG.ui.darkMode) {
document.body.classList.add('enhancer-dark');
}
applyPerformanceSettings();
createFPSCounter();
createCustomCrosshair();
createHitmarker();
createDamageOverlay();
createSettingsPanel();
hookGameEvents();
requestAnimationFrame(updateFPS);
setInterval(() => {
applyPerformanceSettings();
}, 5000);
setInterval(() => {
createCustomCrosshair();
}, 1000);
console.log('%c[Enhancer] Krunker.io Enhancer v2.1 Loaded!', 'color: #00ff00; font-size: 16px; font-weight: bold;');
console.log('%c[Enhancer] Press F1 to open settings', 'color: #888;');
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();