premium omoggle script
Stan na
// ==UserScript==
// @name cheatmoggle
// @namespace https://omoggle.com/
// @version 13.3.0
// @description premium omoggle script
// @match https://omoggle.com/*
// @match https://*.omoggle.com/*
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
// Use unsafeWindow to access the page's real window object (for Tampermonkey compatibility)
const _window = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
const DEFAULT_CONFIG = {
enabled: true,
scoreEnabled: true,
scoreMode: 'range',
fixedScore: 94000,
scoreRangeMin: 85000,
scoreRangeMax: 95000,
resultEnabled: true,
myFinalScore: "94000",
finalScoreMode: 'fixed',
finalScoreRangeMin: 85000,
finalScoreRangeMax: 97000,
holdBtnSize: 54,
debug: true,
wmAlpha: 20,
wmFontSize: 9,
wmPaddingH: 14,
wmPaddingV: 6,
wmBorder: true,
wmBg: true,
theme: 'crimson'
};
function loadConfig() {
try {
const saved = localStorage.getItem('cheatmoggle_config');
if (saved) return { ...DEFAULT_CONFIG, ...JSON.parse(saved) };
} catch (e) {}
return { ...DEFAULT_CONFIG };
}
function saveConfig() {
try {
localStorage.setItem('cheatmoggle_config', JSON.stringify(CONFIG));
} catch (e) {}
}
const CONFIG = loadConfig();
const THEMES = {
amoled: {
name: 'AMOLED',
primary: '#000000',
primaryRgb: '0,0,0',
secondary: '#171717',
accent: '#ffffff',
accentRgb: '255,255,255',
success: '#22c55e',
warning: '#eab308',
danger: '#ef4444',
bgDark: '#000000',
bgCard: '#0a0a0a',
bgElevated: '#141414',
border: 'rgba(255,255,255,0.15)',
text: '#ffffff',
textMuted: '#a1a1aa'
},
neon: {
name: 'Neon',
primary: '#00ff88',
primaryRgb: '0,255,136',
secondary: '#00cc6a',
accent: '#7dffb3',
accentRgb: '125,255,179',
success: '#00ff88',
warning: '#ffcc00',
danger: '#ff4444',
bgDark: '#0a0f0c',
bgCard: '#0d1a12',
bgElevated: '#132218',
border: 'rgba(0,255,136,0.15)',
text: '#e0ffe8',
textMuted: '#7da88a'
},
matrix: {
name: 'Matrix',
primary: '#00ff00',
primaryRgb: '0,255,0',
secondary: '#00cc00',
accent: '#66ff66',
accentRgb: '102,255,102',
success: '#00ff00',
warning: '#ccff00',
danger: '#ff3333',
bgDark: '#000800',
bgCard: '#001a00',
bgElevated: '#002200',
border: 'rgba(0,255,0,0.12)',
text: '#ccffcc',
textMuted: '#669966'
},
toxic: {
name: 'Toxic',
primary: '#39ff14',
primaryRgb: '57,255,20',
secondary: '#7fff00',
accent: '#adff2f',
accentRgb: '173,255,47',
success: '#39ff14',
warning: '#ffff00',
danger: '#ff6347',
bgDark: '#080a05',
bgCard: '#101408',
bgElevated: '#181f0c',
border: 'rgba(57,255,20,0.12)',
text: '#e8ffe0',
textMuted: '#8faa7d'
},
midnight: {
name: 'Midnight',
primary: '#6366f1',
primaryRgb: '99,102,241',
secondary: '#8b5cf6',
accent: '#22d3ee',
accentRgb: '34,211,238',
success: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
bgDark: '#0a0a0f',
bgCard: '#12121a',
bgElevated: '#1a1a24',
border: 'rgba(255,255,255,0.08)',
text: '#e4e4e7',
textMuted: '#71717a'
},
crimson: {
name: 'Crimson',
primary: '#dc2626',
primaryRgb: '220,38,38',
secondary: '#f43f5e',
accent: '#fb7185',
accentRgb: '251,113,133',
success: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
bgDark: '#0f0505',
bgCard: '#1a0a0a',
bgElevated: '#241010',
border: 'rgba(255,100,100,0.1)',
text: '#fecaca',
textMuted: '#a8a29e'
}
};
let playerMapping = null;
let _isRanked = window.location.pathname.startsWith('/ranked');
let _matchStartTime = null;
let _finalScoreAppliedThisMatch = false;
const _origPushState = history.pushState;
history.pushState = function(...args) {
_origPushState.apply(this, args);
_isRanked = window.location.pathname.startsWith('/ranked');
};
window.addEventListener('popstate', () => {
_isRanked = window.location.pathname.startsWith('/ranked');
});
function tryDecode(data) {
try {
const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
if (!(bytes instanceof Uint8Array)) return null;
const text = new TextDecoder().decode(bytes);
const jsonMatch = text.match(/\{[^}]+\}/);
if (jsonMatch) return { json: JSON.parse(jsonMatch[0]), bytes, fullText: text };
} catch (e) {}
return null;
}
function rewriteBytes(originalBytes, oldJSON, newJSON) {
const originalText = new TextDecoder().decode(originalBytes);
const newText = originalText.replace(JSON.stringify(oldJSON), JSON.stringify(newJSON));
return new TextEncoder().encode(newText);
}
const originalSend = RTCDataChannel.prototype.send;
RTCDataChannel.prototype.send = function (data) {
const parsed = tryDecode(data);
if (parsed?.json) {
const { json, bytes } = parsed;
const hasP = typeof json.p !== 'undefined';
const hasQ = typeof json.q !== 'undefined';
const isNormalFrame = hasP && hasQ && json.m === undefined && !json.type;
const isRankedFrame = hasP && hasQ && json.m !== undefined;
if (isRankedFrame && !_isRanked) {
_isRanked = true;
log('Locked: RANKED mode (m field detected in frame)');
}
if (isNormalFrame || isRankedFrame) {
if (json.p <= 2 && _matchStartTime === null) {
_matchStartTime = Date.now();
_finalScoreAppliedThisMatch = false;
log(`Match started - tracking time from now`);
}
if (!playerMapping && json.q > 0) {
playerMapping = { myKey: 'q' };
log(`q confirmed as your score [${isRankedFrame ? 'RANKED' : 'NORMAL'} frame]`);
}
if (json.q > 0) {
if (!CONFIG.scoreEnabled) {
return originalSend.call(this, data);
}
const modified = { ...json };
let newScore;
const matchElapsed = _matchStartTime ? (Date.now() - _matchStartTime) / 1000 : 0;
const shouldUseFinalScore = CONFIG.resultEnabled && matchElapsed >= 14;
if (shouldUseFinalScore) {
newScore = _getFinalTarget();
if (!_finalScoreAppliedThisMatch) {
_finalScoreAppliedThisMatch = true;
log(`[FINAL SCORE] Match at ${matchElapsed.toFixed(1)}s - switching to final score: ${newScore} (${newScore/10000})`);
}
} else if (CONFIG.scoreMode === 'fixed') {
newScore = CONFIG.fixedScore;
log(`[FIXED MODE] Using fixed score: ${newScore} (${newScore/10000})`);
} else {
if (_dynamicCap === null) {
_dynamicCap = Math.round((CONFIG.scoreRangeMin + CONFIG.scoreRangeMax) / 2000) * 1000;
}
if (Math.random() < 0.5) {
_dynamicCap += 1000;
} else {
_dynamicCap -= 1000;
}
_dynamicCap = Math.max(CONFIG.scoreRangeMin, Math.min(CONFIG.scoreRangeMax, _dynamicCap));
newScore = _dynamicCap;
}
modified.q = newScore;
if (json.m !== undefined) modified.m = json.m;
if (json.type !== undefined) modified.type = json.type;
log(`[${isRankedFrame ? 'RANKED' : 'NORMAL'}] frame=${json.p} q: ${json.q}→${modified.q} (${(json.q/10000).toFixed(2)}→${(modified.q/10000).toFixed(2)})`);
_lastSpoofedScore = modified.q / 10000;
spoofPanel();
return originalSend.call(this, rewriteBytes(bytes, json, modified));
}
}
const isRankedScoreType = json.type === "RANKED_SCORE" && typeof json.score !== "undefined";
if (isRankedScoreType && CONFIG.scoreEnabled) {
const modified = { ...json };
if (CONFIG.scoreMode === 'fixed') {
modified.score = CONFIG.fixedScore / 10000;
} else {
if (_dynamicCap === null) {
_dynamicCap = Math.round((CONFIG.scoreRangeMin + CONFIG.scoreRangeMax) / 2000) * 1000;
}
modified.score = _dynamicCap / 10000;
}
modified.score = Math.min(modified.score, 10);
_lastSpoofedScore = modified.score;
log(`[RANKED_SCORE type] score: ${json.score}→${modified.score}`);
spoofPanel();
return originalSend.call(this, rewriteBytes(bytes, json, modified));
}
}
return originalSend.call(this, data);
};
const origOnMessageDesc = Object.getOwnPropertyDescriptor(RTCDataChannel.prototype, 'onmessage');
if (origOnMessageDesc) {
Object.defineProperty(RTCDataChannel.prototype, 'onmessage', {
set(fn) {
origOnMessageDesc.set.call(this, function(event) {
const parsed = tryDecode(event.data);
if (parsed?.json) {
const { json } = parsed;
if (typeof json.p !== 'undefined' && typeof json.q !== 'undefined' && !json.type && json.q > 0) {
log(`OPP frame=${json.p} score=${(json.q/10000).toFixed(2)}`);
}
}
return fn.call(this, event);
});
},
get: origOnMessageDesc.get,
configurable: true
});
}
const originalAEL = RTCDataChannel.prototype.addEventListener;
RTCDataChannel.prototype.addEventListener = function (type, listener, options) {
if (type !== 'message' || typeof listener !== 'function')
return originalAEL.call(this, type, listener, options);
const wrapped = function (event) {
const parsed = tryDecode(event.data);
if (parsed?.json) {
const { json } = parsed;
if (typeof json.p !== 'undefined' && typeof json.q !== 'undefined' && !json.type && json.q > 0) {
log(`OPP (AEL) frame=${json.p} score=${(json.q/10000).toFixed(2)}`);
}
}
return listener.call(this, event);
};
return originalAEL.call(this, type, wrapped, options);
};
// ─── FINALIZE SCORE FIELDS (matches actual payload structure) ───────────
const FINALIZE_SCORE_FIELDS = [
'selfScore', 'player1Score', 'player2Score',
'hostScore', 'actualScore', 'verifiedScore',
'serverScore', 'realFinalScore', 'clientScore',
'adjustedScore', 'opponentScore'
];
const origFetch = _window.fetch;
_window.fetch = async function(url, options) {
const urlStr = typeof url === 'string' ? url : (url?.url || '');
if (urlStr.includes('/api/match/finalize') || urlStr.includes('/api/ranked/finalize')) {
if (options?.body && CONFIG.resultEnabled) {
try {
const body = JSON.parse(options.body);
log('FINALIZE (original):', JSON.stringify(body).substring(0, 500));
const finalTarget = _getFinalTarget();
const finalFloat = finalTarget / 10000;
let patched = false;
// Strategy 1: legacy nested score object (body.u or body.i)
const scoreObj = body.u || body.i;
if (scoreObj && scoreObj.e !== undefined) {
const realE = parseInt(scoreObj.e) || 0;
scoreObj.e = String(finalTarget);
if (body.i) _isRanked = true;
log(`[LEGACY] score.e: ${realE} → ${scoreObj.e}`);
patched = true;
}
// Strategy 2: flat score fields on body (new structure from logs)
for (const field of FINALIZE_SCORE_FIELDS) {
if (field in body && body[field] !== undefined) {
// Only patch "my" score fields, not opponent's
if (field === 'opponentScore' || field === 'rivalScore') continue;
const old = body[field];
// Values are stored as raw ints (e.g. 94000) or floats (9.4)
// Detect which format by magnitude
if (typeof old === 'number') {
body[field] = old > 100 ? finalTarget : finalFloat;
log(`[FLAT] ${field}: ${old} → ${body[field]}`);
patched = true;
} else if (typeof old === 'string') {
body[field] = String(old > '100' ? finalTarget : finalFloat);
log(`[FLAT STR] ${field}: ${old} → ${body[field]}`);
patched = true;
}
}
}
// Strategy 3: settlement / hud scores arrays
if (body.settlement?.scores && Array.isArray(body.settlement.scores)) {
const s = body.settlement.scores;
const myIdx = s[0] >= s[1] ? 0 : 1;
const old = s[myIdx];
s[myIdx] = old > 100 ? finalTarget : finalFloat;
log(`[SETTLEMENT] scores[${myIdx}]: ${old} → ${s[myIdx]}`);
patched = true;
}
if (body.hud?.scores && Array.isArray(body.hud.scores)) {
const s = body.hud.scores;
const myIdx = s[0] >= s[1] ? 0 : 1;
const old = s[myIdx];
s[myIdx] = old > 100 ? finalTarget : finalFloat;
log(`[HUD] scores[${myIdx}]: ${old} → ${s[myIdx]}`);
patched = true;
}
if (!patched) {
log('[FINALIZE] No known score fields found in body — sending as-is');
}
options = { ...options, body: JSON.stringify(body) };
log('FINALIZE REQUEST (modified):', JSON.stringify(body));
} catch(e) {
log('Could not parse finalize body:', e);
}
}
const response = await origFetch.call(this, url, options);
const clone = response.clone();
clone.json().then(data => {
log('FINALIZE RESPONSE:', JSON.stringify(data));
if (response.ok) {
_lockedFinalTarget = null;
_finalApplied = false;
_lastSpoofedScore = null;
_matchStartTime = null;
_finalScoreAppliedThisMatch = false;
}
}).catch(() => {});
return response;
}
// ── BOOSTED_STATS: only keep is_pro, no fake ELO/wins/streaks ──────
const BOOSTED_STATS = {
is_pro: true,
};
if (urlStr.includes('supabase.co/rest/v1/profiles')) {
const response = await origFetch.call(this, url, options);
const clone = response.clone();
try {
const data = await clone.json();
if (Array.isArray(data) && data.length > 0) {
const modified = data.map(profile => ({ ...profile, ...BOOSTED_STATS }));
const newHeaders = new Headers(response.headers);
newHeaders.set('content-type', 'application/json');
return new Response(JSON.stringify(modified), {
status: response.status,
statusText: response.statusText,
headers: newHeaders
});
}
} catch(e) {}
return response;
}
if (urlStr.includes('/api/profiles/public/')) {
const response = await origFetch.call(this, url, options);
const clone = response.clone();
try {
const data = await clone.json();
if (data && data.profile) {
const modified = {
...data,
profile: {
...data.profile,
is_pro: true,
}
};
return new Response(JSON.stringify(modified), {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
}
} catch(e) {}
return response;
}
if (urlStr.includes('/api/profile/ranked-stats')) {
const response = await origFetch.call(this, url, options);
return response;
}
if (urlStr.includes('/api/profile/world-rank')) {
const response = await origFetch.call(this, url, options);
return response;
}
if (urlStr.includes('/api/profile/lobby-summary')) {
const response = await origFetch.call(this, url, options);
const clone = response.clone();
try {
const data = await clone.json();
if (data && typeof data === 'object') {
const modified = {
...data,
is_pro: true,
};
return new Response(JSON.stringify(modified), {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
}
} catch(e) {}
return response;
}
if (urlStr === '/api/profile' || urlStr.endsWith('/api/profile')) {
const response = await origFetch.call(this, url, options);
const clone = response.clone();
try {
const data = await clone.json();
if (data && data.profile) {
const modified = {
...data,
profile: {
...data.profile,
is_pro: true,
}
};
return new Response(JSON.stringify(modified), {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
}
} catch(e) {}
return response;
}
return origFetch.call(this, url, options);
};
let _lockedFinalTarget = null;
let _lastFinalMode = null;
let _finalApplied = false;
function _getFinalTarget() {
if (_lockedFinalTarget === null || _lastFinalMode !== CONFIG.finalScoreMode) {
_finalApplied = false;
_lastFinalMode = CONFIG.finalScoreMode;
if (CONFIG.finalScoreMode === 'range') {
_lockedFinalTarget = Math.round(CONFIG.finalScoreRangeMin + Math.random() * (CONFIG.finalScoreRangeMax - CONFIG.finalScoreRangeMin));
} else {
_lockedFinalTarget = parseInt(CONFIG.myFinalScore);
}
log(`_getFinalTarget locked: ${_lockedFinalTarget} (${CONFIG.finalScoreMode})`);
}
if (CONFIG.finalScoreMode === 'fixed') {
return parseInt(CONFIG.myFinalScore);
}
return _lockedFinalTarget;
}
// ─── ZUSTAND STORE PATCH ────────────────────────────────────────────────
function patchZustandStore() {
try {
const wpChunk = _window.webpackChunk_N_E || _window.webpackChunknextjs_app || _window.webpackChunk;
if (!wpChunk) return false;
let req;
try {
req = wpChunk.push([[Symbol()], {}, e => e]);
} catch(e) { return false; }
if (typeof req !== 'function') return false;
let store = null;
try {
const mod = req(16225);
if (mod) {
store = Object.values(mod).find(val =>
val && typeof val.getState === 'function' &&
'selfScore' in (val.getState() || {})
);
}
} catch(e) {}
if (!store && req.m) {
for (const id of Object.keys(req.m)) {
try {
const mod = req(id);
if (!mod || typeof mod !== 'object') continue;
const found = Object.values(mod).find(val =>
val && typeof val.getState === 'function' &&
'selfScore' in (val.getState() || {})
);
if (found) {
store = found;
log(`Found Zustand store via scan in module ${id}`);
break;
}
} catch(e) {}
}
}
if (!store) return false;
return patchStore(store);
} catch(e) {
log('patchZustandStore error:', e);
return false;
}
}
function patchStore(store) {
try {
const state = store.getState();
const origSetMyScore = state.setMyScore;
if (origSetMyScore && !origSetMyScore.__patched) {
store.setState({
setMyScore: function(score) {
if (!CONFIG.scoreEnabled) return origSetMyScore.call(this, score);
let boosted;
if (CONFIG.scoreMode === 'fixed') {
boosted = CONFIG.fixedScore / 10000;
} else {
if (_dynamicCap === null) {
_dynamicCap = Math.round((CONFIG.scoreRangeMin + CONFIG.scoreRangeMax) / 2000) * 1000;
}
boosted = _dynamicCap / 10000;
}
log(`setMyScore: ${score.toFixed(2)} → ${boosted.toFixed(2)}`);
_lastSpoofedScore = boosted;
spoofPanel();
return origSetMyScore.call(this, boosted);
}
});
store.getState().setMyScore.__patched = true;
log('setMyScore patched');
}
const origApply = state.applyFinalScores;
if (origApply && !origApply.__patched) {
store.setState({
applyFinalScores: function(p1, p2, iAmPlayer1) {
log('applyFinalScores called — injecting final target');
const target = _getFinalTarget();
const myScore = target / 10000;
const newP1 = iAmPlayer1 ? myScore : p1;
const newP2 = iAmPlayer1 ? p2 : myScore;
log(`applyFinalScores → p1=${newP1} p2=${newP2} iAmPlayer1=${iAmPlayer1}`);
_finalApplied = true;
_lastSpoofedScore = null;
return origApply.call(this, newP1, newP2, iAmPlayer1);
}
});
store.getState().applyFinalScores.__patched = true;
log('applyFinalScores patched');
}
return true;
} catch(e) {
log('patchStore error:', e);
return false;
}
}
let patchAttempts = 0;
const patchPoll = setInterval(() => {
patchAttempts++;
if (patchZustandStore()) {
clearInterval(patchPoll);
log(`Zustand store patched after ${patchAttempts} attempts`);
} else if (patchAttempts % 50 === 0) {
log(`Still looking for Zustand store... (attempt ${patchAttempts})`);
}
}, 200);
// ── TIER_MAP: Adam removed, Slayer is now the top tier ─────────────────
const TIER_MAP = [
{ name: 'Slayer', emoji: '☠️', hexColor: '#f472b6', textShadow: '0 0 12px rgba(244,114,182,0.9)', min: 9.5 },
{ name: 'Chad', emoji: '👑', hexColor: '#fb923c', textShadow: '0 0 10px rgba(251,146,60,0.8)', min: 8.9 },
{ name: 'Chadlite', emoji: '⚜️', hexColor: '#facc15', textShadow: '0 0 8px rgba(250,204,21,0.8)', min: 8.3 },
{ name: 'HTN', emoji: '🌟', hexColor: '#a3e635', textShadow: '0 0 8px rgba(163,230,53,0.8)', min: 7.0 },
{ name: 'MTN', emoji: '⭐', hexColor: '#86efac', textShadow: '0 0 6px rgba(134,239,172,0.7)', min: 5.6 },
{ name: 'LTN', emoji: '🌙', hexColor: '#34d399', textShadow: '0 0 6px rgba(52,211,153,0.6)', min: 3.1 },
{ name: 'Sub3', emoji: '🦀', hexColor: '#b45309', textShadow: '0 0 6px rgba(180,83,9,0.7)', min: 0.1 },
];
let _lastSpoofedScore = null;
let _dynamicCap = null;
function getTierForScore(score) {
for (const tier of TIER_MAP) {
if (score >= tier.min) return tier;
}
return TIER_MAP[TIER_MAP.length - 1];
}
function spoofPanel() {
if (_lastSpoofedScore === null) return;
const displayScore = _lastSpoofedScore;
const tier = getTierForScore(displayScore);
const myPanel = document.querySelector('.glass-panel.absolute.top-5') ||
document.querySelector('.glass-panel.absolute.top-8') ||
document.querySelector('[class*="glass-panel"][class*="absolute"][class*="left"]') ||
document.querySelector('[class*="glass-panel"][class*="absolute"][class*="top"]') ||
document.querySelector('[class*="ranked"][class*="score"]') ||
document.querySelector('[class*="player-score"]') ||
document.querySelector('[class*="my-score"]') ||
(() => {
const allPanels = document.querySelectorAll('[class*="glass"], [class*="panel"], [class*="score-card"]');
for (const p of allPanels) {
const spans = p.querySelectorAll('span.font-mono');
for (const s of spans) {
if (/^\d+\.?\d*$/.test(s.textContent.trim())) return p;
}
}
return null;
})();
if (!myPanel) return;
const allMono = myPanel.querySelectorAll('span.font-mono');
let scoreSpan = null;
for (const s of allMono) {
if (/^\d+\.?\d*$/.test(s.textContent.trim())) {
scoreSpan = s;
break;
}
}
if (!scoreSpan) return;
if (scoreSpan.textContent.trim() !== displayScore.toFixed(1)) {
scoreSpan.textContent = displayScore.toFixed(1);
}
const tierSpan = scoreSpan.nextElementSibling;
if (tierSpan) {
const want = `${tier.emoji} ${tier.name}`;
if (tierSpan.textContent !== want) tierSpan.textContent = want;
if (tierSpan.style.color !== tier.hexColor) tierSpan.style.color = tier.hexColor;
if (tierSpan.style.textShadow !== tier.textShadow) tierSpan.style.textShadow = tier.textShadow;
}
const allSpans = myPanel.querySelectorAll('span');
for (const span of allSpans) {
if (span === scoreSpan) continue;
const t = span.textContent.trim();
const tierNames = ['Slayer','Chad','Chadlite','HTN','MTN','LTN','Sub3'];
if (tierNames.some(n => t.includes(n)) && !t.includes(tier.name)) {
span.textContent = `${tier.emoji} ${tier.name}`;
span.style.color = tier.hexColor;
span.style.textShadow = tier.textShadow;
}
if (span.style.color && span.style.color !== tier.hexColor) {
const tierColors = ['#f472b6','#fb923c','#facc15','#a3e635','#86efac','#34d399','#b45309'];
if (tierColors.includes(span.style.color)) {
span.style.color = tier.hexColor;
span.style.textShadow = tier.textShadow;
}
}
}
}
const _panelObserver = new MutationObserver(spoofPanel);
let _observedPanel = null;
function attachPanelObserver() {
const myPanel = document.querySelector('.glass-panel.absolute.top-5') ||
document.querySelector('.glass-panel.absolute.top-8') ||
document.querySelector('[class*="glass-panel"][class*="absolute"][class*="left"]') ||
document.querySelector('[class*="glass-panel"][class*="absolute"][class*="top"]') ||
document.querySelector('[class*="ranked"][class*="score"]') ||
document.querySelector('[class*="player-score"]') ||
document.querySelector('[class*="my-score"]') ||
(() => {
const allPanels = document.querySelectorAll('[class*="glass"], [class*="panel"], [class*="score-card"]');
for (const p of allPanels) {
const spans = p.querySelectorAll('span.font-mono');
for (const s of spans) {
if (/^\d+\.?\d*$/.test(s.textContent.trim())) return p;
}
}
return null;
})();
if (myPanel && myPanel !== _observedPanel) {
if (_observedPanel) _panelObserver.disconnect();
_panelObserver.observe(myPanel, { childList: true, subtree: true, characterData: true });
_observedPanel = myPanel;
}
}
setInterval(() => { attachPanelObserver(); spoofPanel(); }, 16);
const OriginalWebSocket = _window.WebSocket;
_window.WebSocket = function(...args) {
const ws = new OriginalWebSocket(...args);
ws.addEventListener('message', function(event) {
if (typeof event.data === 'string') {
if (event.data.includes('FINAL_SCORES') || event.data.includes('elo') || event.data.includes('score')) {
log('WS TEXT:', event.data);
}
return;
}
const buf = event.data instanceof ArrayBuffer ? event.data : null;
if (!buf) return;
const bytes = new Uint8Array(buf);
const size = bytes.length;
const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes);
const strings = text.match(/[\x20-\x7E]{4,}/g) || [];
if (size === 108 || size > 50) {
log(`WS RECV binary [${size} bytes] strings:`, strings);
strings.forEach(s => {
if (/\d\.\d/.test(s) || s.includes('score') || s.includes('win') || s.includes('elo')) {
log(' Possible score string:', s);
}
});
}
});
return ws;
};
Object.setPrototypeOf(_window.WebSocket, OriginalWebSocket);
_window.WebSocket.prototype = OriginalWebSocket.prototype;
['CONNECTING','OPEN','CLOSING','CLOSED'].forEach(k => {
try {
Object.defineProperty(_window.WebSocket, k, {
value: OriginalWebSocket[k],
writable: false,
configurable: true
});
} catch(e) {}
});
log('v13.3 cheatmoggle loaded');
const _trueOriginalGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
let _camSpoofActive = false;
let _camStream = null;
navigator.mediaDevices.getUserMedia = async function(constraints) {
if (_camSpoofActive && _camStream && constraints && (constraints.video || constraints.video === true)) {
log('[CAM SPOOF] Intercepting getUserMedia - returning spoofed stream');
setTimeout(() => {
const scannerVid = document.querySelector('video.scanner-video');
if (scannerVid) scannerVid.srcObject = _camStream;
if (window._mogPCs) {
const fakeTrack = _camStream.getVideoTracks()[0];
for (const pc of window._mogPCs) {
try {
pc.getSenders().forEach(sender => {
if (sender.track?.kind === 'video') {
sender.replaceTrack(fakeTrack).catch(() => {});
}
});
} catch(e) {}
}
}
}, 100);
if (constraints.audio) {
try {
const realAudio = await _trueOriginalGetUserMedia({ audio: constraints.audio });
return new MediaStream([
..._camStream.getVideoTracks(),
...realAudio.getAudioTracks()
]);
} catch(e) {
return _camStream;
}
}
return _camStream;
}
const stream = await _trueOriginalGetUserMedia(constraints);
stream.getVideoTracks().forEach(t => {
t.addEventListener('ended', () => log('VIDEO TRACK ENDED:', t.label));
t.addEventListener('mute', () => log('VIDEO TRACK MUTED:', t.label));
});
return stream;
};
const _OrigRTCPC = window.RTCPeerConnection;
window.RTCPeerConnection = function(...args) {
const pc = new _OrigRTCPC(...args);
const _origAddTrack = pc.addTrack.bind(pc);
pc.addTrack = function(track, ...streams) {
return _origAddTrack(track, ...streams);
};
return pc;
};
Object.setPrototypeOf(window.RTCPeerConnection, _OrigRTCPC);
window.RTCPeerConnection.prototype = _OrigRTCPC.prototype;
// ══════════════════════════════════════════════════════════════════════════
// CHEATMOGGLE UI
// ══════════════════════════════════════════════════════════════════════════
function buildMenu() {
if (document.getElementById('cm-root')) return;
function applyTheme(themeName) {
const theme = THEMES[themeName] || THEMES.midnight;
CONFIG.theme = themeName;
document.documentElement.style.setProperty('--cm-primary', theme.primary);
document.documentElement.style.setProperty('--cm-primary-rgb', theme.primaryRgb);
document.documentElement.style.setProperty('--cm-secondary', theme.secondary);
document.documentElement.style.setProperty('--cm-accent', theme.accent);
document.documentElement.style.setProperty('--cm-accent-rgb', theme.accentRgb);
document.documentElement.style.setProperty('--cm-success', theme.success);
document.documentElement.style.setProperty('--cm-warning', theme.warning);
document.documentElement.style.setProperty('--cm-danger', theme.danger);
document.documentElement.style.setProperty('--cm-bg-dark', theme.bgDark);
document.documentElement.style.setProperty('--cm-bg-card', theme.bgCard);
document.documentElement.style.setProperty('--cm-bg-elevated', theme.bgElevated);
document.documentElement.style.setProperty('--cm-border', theme.border);
document.documentElement.style.setProperty('--cm-text', theme.text);
document.documentElement.style.setProperty('--cm-text-muted', theme.textMuted);
saveConfig();
}
const style = document.createElement('style');
style.textContent = `
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');
:root {
--cm-primary: #00ff88;
--cm-primary-rgb: 0,255,136;
--cm-secondary: #00cc6a;
--cm-accent: #7dffb3;
--cm-accent-rgb: 125,255,179;
--cm-success: #00ff88;
--cm-warning: #ffcc00;
--cm-danger: #ff4444;
--cm-bg-dark: #0a0f0c;
--cm-bg-card: #0d1a12;
--cm-bg-elevated: #132218;
--cm-border: rgba(0,255,136,0.15);
--cm-text: #e0ffe8;
--cm-text-muted: #7da88a;
--cm-glow: 0 0 30px rgba(var(--cm-primary-rgb),0.3);
}
#cm-toggle-btn {
position: fixed;
top: 16px;
right: 16px;
z-index: 999999;
width: 32px;
height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary));
border: none;
cursor: grab;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 12px rgba(var(--cm-primary-rgb),0.3), 0 1px 4px rgba(0,0,0,0.2);
transition: transform 0.15s, box-shadow 0.15s;
user-select: none;
touch-action: none;
}
#cm-toggle-btn:active { cursor: grabbing; }
#cm-toggle-btn:hover {
transform: scale(1.05);
box-shadow: 0 4px 16px rgba(var(--cm-primary-rgb),0.4), 0 2px 6px rgba(0,0,0,0.3);
}
#cm-toggle-btn.dragging { cursor: grabbing; transition: none; }
#cm-toggle-btn svg {
width: 22px;
height: 22px;
fill: white;
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3));
}
#cm-root {
position: fixed;
top: 70px;
right: 16px;
z-index: 999998;
width: 280px;
min-width: 220px;
max-width: 90vw;
max-height: 70vh;
min-height: 200px;
background: var(--cm-bg-dark);
border-radius: 12px;
font-family: 'Inter', -apple-system, sans-serif;
color: var(--cm-text);
border: 1px solid var(--cm-border);
box-shadow: 0 0 40px rgba(var(--cm-primary-rgb),0.1), 0 15px 30px rgba(0,0,0,0.4);
display: none;
opacity: 0;
overflow: hidden;
transition: opacity 0.2s ease, transform 0.2s ease;
transform: translateY(-10px) scale(0.98);
resize: both;
}
#cm-root.visible {
display: flex;
flex-direction: column;
opacity: 1;
transform: translateY(0) scale(1);
}
#cm-root.dragging { transition: none; user-select: none; }
.cm-header {
padding: 8px 10px 6px;
background: linear-gradient(180deg, rgba(var(--cm-primary-rgb),0.08) 0%, transparent 100%);
border-bottom: 1px solid var(--cm-border);
cursor: grab;
user-select: none;
flex-shrink: 0;
}
.cm-header:active { cursor: grabbing; }
.cm-title-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 6px;
}
.cm-logo { display: flex; align-items: center; gap: 6px; }
.cm-logo-icon {
width: 24px; height: 24px;
border-radius: 6px;
background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary));
display: flex; align-items: center; justify-content: center;
box-shadow: 0 2px 8px rgba(var(--cm-primary-rgb),0.3);
}
.cm-logo-icon svg { width: 14px; height: 14px; fill: white; }
.cm-title {
font-family: 'Space Grotesk', sans-serif;
font-size: 13px; font-weight: 700; letter-spacing: -0.02em;
background: linear-gradient(135deg, #fff 0%, var(--cm-accent) 100%);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
.cm-version {
font-size: 8px; font-weight: 600; color: var(--cm-text-muted);
background: var(--cm-bg-elevated); padding: 1px 4px; border-radius: 3px; margin-left: 4px;
}
.cm-status-row { display: flex; align-items: center; gap: 4px; }
.cm-pill {
padding: 2px 5px; border-radius: 4px;
font-size: 8px; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.04em;
}
.cm-pill.active {
background: rgba(16,185,129,0.2); color: var(--cm-success);
border: 1px solid rgba(16,185,129,0.3);
}
.cm-pill.mode {
background: rgba(var(--cm-primary-rgb),0.2); color: var(--cm-primary);
border: 1px solid rgba(var(--cm-primary-rgb),0.3);
}
.cm-discord-link {
display: flex; align-items: center; gap: 6px;
padding: 6px 10px;
background: linear-gradient(135deg, #5865F2 0%, #7289da 100%);
border-radius: 8px; font-size: 10px; font-weight: 600;
color: white; text-decoration: none; transition: all 0.2s ease; margin-left: auto;
}
.cm-discord-link:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(88,101,242,0.4); }
.cm-discord-link svg { width: 14px; height: 14px; fill: currentColor; }
.cm-tabs {
display: flex; gap: 2px;
background: var(--cm-bg-card); padding: 2px; border-radius: 6px;
}
.cm-tab {
flex: 1; padding: 5px 4px; border-radius: 4px;
font-size: 9px; font-weight: 600; text-align: center;
cursor: pointer; transition: all 0.15s ease;
color: var(--cm-text-muted); background: transparent; border: none; white-space: nowrap;
}
.cm-tab:hover { color: var(--cm-text); background: rgba(255,255,255,0.03); }
.cm-tab.active {
background: var(--cm-bg-elevated); color: white;
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
.cm-body { padding: 8px; overflow-y: auto; flex: 1; }
.cm-body::-webkit-scrollbar { width: 4px; }
.cm-body::-webkit-scrollbar-track { background: transparent; }
.cm-body::-webkit-scrollbar-thumb { background: rgba(var(--cm-primary-rgb),0.3); border-radius: 2px; }
.cm-panel { display: none; }
.cm-panel.active { display: block; animation: cmFadeIn 0.2s ease; }
@keyframes cmFadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.cm-section { margin-bottom: 8px; }
.cm-section:last-child { margin-bottom: 0; }
.cm-section-title {
font-size: 8px; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.1em;
color: var(--cm-text-muted); margin-bottom: 4px;
display: flex; align-items: center; gap: 4px; justify-content: space-between;
}
.cm-section-title > span { display: flex; align-items: center; gap: 4px; }
.cm-section-title > span::after {
content: ''; width: 20px; height: 1px;
background: linear-gradient(90deg, var(--cm-border), transparent);
}
.cm-section-toggle { transform: scale(0.7); }
.cm-section-disabled { opacity: 0.4; pointer-events: none; }
.cm-divider { height: 1px; background: var(--cm-border); margin: 10px 0; }
.cm-card {
background: var(--cm-bg-card); border-radius: 8px;
padding: 6px; border: 1px solid var(--cm-border);
}
.cm-live-score {
text-align: center; padding: 8px 6px;
background: linear-gradient(135deg, rgba(var(--cm-primary-rgb),0.08), rgba(var(--cm-accent-rgb),0.05));
border-radius: 8px;
}
.cm-score-value {
font-family: 'JetBrains Mono', monospace;
font-size: 24px; font-weight: 800; letter-spacing: -0.02em; line-height: 1; margin-bottom: 2px;
}
.cm-score-tier { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.cm-row {
display: flex; align-items: center; justify-content: space-between;
padding: 4px 0; border-bottom: 1px solid var(--cm-border);
}
.cm-row:last-child { border-bottom: none; }
.cm-label { font-size: 10px; font-weight: 500; color: var(--cm-text); }
.cm-value { font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600; color: var(--cm-text); }
.cm-slider-row { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; border-bottom: 1px solid var(--cm-border); }
.cm-slider-row:last-child { border-bottom: none; }
.cm-slider-header { display: flex; justify-content: space-between; align-items: center; }
.cm-slider-label { font-size: 9px; font-weight: 500; }
.cm-slider-value {
font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600; color: var(--cm-text);
background: var(--cm-bg-elevated); border: 1px solid var(--cm-border); padding: 1px 4px; border-radius: 3px;
}
.cm-slider-track {
position: relative; height: 4px;
background: var(--cm-bg-elevated); border-radius: 2px; overflow: hidden; border: 1px solid var(--cm-border);
}
.cm-slider-fill {
position: absolute; top: 0; left: 0; height: 100%;
background: var(--cm-text-muted); border-radius: 2px; transition: width 0.1s ease; opacity: 0.4;
}
.cm-slider {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
-webkit-appearance: none; background: transparent; cursor: pointer; margin: 0;
}
.cm-slider::-webkit-slider-thumb {
-webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;
background: var(--cm-text); cursor: pointer;
box-shadow: 0 2px 6px rgba(0,0,0,0.4); transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.cm-slider::-webkit-slider-thumb:hover { transform: scale(1.15); box-shadow: 0 2px 10px rgba(0,0,0,0.5); }
.cm-toggle { position: relative; width: 32px; height: 18px; cursor: pointer; }
.cm-toggle input { opacity: 0; width: 0; height: 0; }
.cm-toggle-track {
position: absolute; inset: 0; border-radius: 11px;
background: var(--cm-bg-elevated); border: 1px solid var(--cm-border); transition: all 0.25s ease;
}
.cm-toggle input:checked + .cm-toggle-track { background: var(--cm-text); border-color: var(--cm-text); }
.cm-toggle-thumb {
position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%;
background: var(--cm-text); box-shadow: 0 1px 3px rgba(0,0,0,0.3);
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.cm-toggle input:checked ~ .cm-toggle-thumb { left: 16px; background: var(--cm-bg-dark); }
.cm-btn-group { display: flex; gap: 3px; background: var(--cm-bg-elevated); padding: 2px; border-radius: 6px; }
.cm-btn-opt {
padding: 6px 10px; border-radius: 6px; font-size: 10px; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.03em; cursor: pointer; transition: all 0.15s ease;
background: transparent; color: var(--cm-text-muted); border: none;
}
.cm-btn-opt:hover { color: var(--cm-text); }
.cm-btn-opt.active { background: var(--cm-text); color: var(--cm-bg-dark); box-shadow: 0 2px 6px rgba(0,0,0,0.3); }
.cm-preview {
margin-top: 12px; padding: 16px;
background: linear-gradient(135deg, rgba(var(--cm-primary-rgb),0.08), rgba(var(--cm-accent-rgb),0.05));
border-radius: 10px; text-align: center; border: 1px solid rgba(var(--cm-primary-rgb),0.15);
}
.cm-preview-score { font-family: 'JetBrains Mono', monospace; font-size: 32px; font-weight: 800; }
.cm-preview-tier { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-top: 4px; }
.cm-file-picker {
display: flex; align-items: center; gap: 8px; padding: 8px;
background: var(--cm-bg-elevated); border: 1px dashed var(--cm-border);
border-radius: 6px; cursor: pointer; transition: all 0.15s ease;
}
.cm-file-picker:hover { border-color: var(--cm-text); background: rgba(var(--cm-accent-rgb),0.05); }
.cm-file-icon {
width: 28px; height: 28px; border-radius: 6px;
background: var(--cm-bg-card); display: flex; align-items: center; justify-content: center;
}
.cm-file-icon svg { width: 14px; height: 14px; fill: var(--cm-text-muted); }
.cm-file-name { font-size: 10px; color: var(--cm-text-muted); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-file-name.selected { color: var(--cm-success); }
.cm-preset-section { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--cm-border); }
.cm-preset-label { font-size: 8px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--cm-text-muted); display: block; margin-bottom: 4px; }
.cm-preset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.cm-preset-btn {
padding: 4px 6px; font-size: 8px; font-weight: 500;
border: 1px solid var(--cm-border); border-radius: 4px;
background: var(--cm-bg-elevated); color: var(--cm-text); cursor: pointer; transition: all 0.15s ease; text-align: center;
}
.cm-preset-btn:hover { background: var(--cm-text); color: var(--cm-bg-dark); border-color: var(--cm-text); }
.cm-preset-btn.active { background: var(--cm-text); color: var(--cm-bg-dark); border-color: var(--cm-text); }
.cm-color-row { display: flex; align-items: center; gap: 10px; }
.cm-color-input { width: 32px; height: 32px; border-radius: 8px; border: none; cursor: pointer; padding: 0; background: none; }
.cm-input {
background: var(--cm-bg-elevated); border: 1px solid var(--cm-border);
border-radius: 6px; padding: 6px 10px;
font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--cm-text);
outline: none; transition: all 0.2s ease;
}
.cm-input:focus { border-color: var(--cm-primary); box-shadow: 0 0 0 2px rgba(var(--cm-primary-rgb),0.2); }
.cm-score-input {
-moz-appearance: textfield;
}
.cm-score-input::-webkit-outer-spin-button,
.cm-score-input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.cm-select {
background: var(--cm-bg-elevated); border: 1px solid var(--cm-border);
border-radius: 6px; padding: 6px 10px;
font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--cm-text);
outline: none; cursor: pointer; transition: all 0.2s ease;
}
.cm-select:focus { border-color: var(--cm-primary); box-shadow: 0 0 0 2px rgba(var(--cm-primary-rgb),0.2); }
.cm-select option { background: var(--cm-bg-dark); color: var(--cm-text); }
.cm-btn-small {
background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary));
border: none; border-radius: 4px; padding: 4px 10px;
font-family: 'Inter', sans-serif; font-size: 10px; font-weight: 600;
color: white; cursor: pointer; transition: all 0.2s ease;
}
.cm-btn-small:hover { transform: scale(1.02); filter: brightness(1.1); }
.cm-shapes { display: flex; gap: 4px; }
.cm-shape-btn {
width: 32px; height: 32px; border-radius: 8px;
border: 1px solid var(--cm-border); background: var(--cm-bg-elevated);
cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease;
}
.cm-shape-btn:hover { background: rgba(var(--cm-primary-rgb),0.15); }
.cm-shape-btn.active { background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary)); border-color: transparent; }
.cm-theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-top: 4px; }
.cm-theme-btn {
padding: 6px 4px; border-radius: 6px; border: 1px solid var(--cm-border);
background: var(--cm-bg-elevated); cursor: pointer; transition: all 0.15s ease; text-align: center;
}
.cm-theme-btn:hover { border-color: rgba(var(--cm-primary-rgb),0.4); }
.cm-theme-btn.active { border-color: var(--cm-text); box-shadow: 0 0 8px rgba(var(--cm-primary-rgb),0.2); }
.cm-theme-preview { width: 16px; height: 16px; border-radius: 4px; margin: 0 auto 3px; }
.cm-theme-name { font-size: 8px; font-weight: 600; color: var(--cm-text); }
.cm-panic-btn {
width: 100%; padding: 6px 10px; font-size: 9px; font-weight: 600;
border: 1px solid var(--cm-danger); border-radius: 4px;
background: rgba(239,68,68,0.1); color: var(--cm-danger); cursor: pointer; transition: all 0.15s ease;
}
.cm-panic-btn:hover { background: var(--cm-danger); color: white; }
#cm-root.stream-hidden,
#cm-toggle-btn.stream-hidden { display: none !important; opacity: 0 !important; pointer-events: none !important; }
#cm-watermark {
position: fixed; bottom: 16px; right: 16px; z-index: 999990;
padding: 6px 12px; border-radius: 8px;
background: rgba(var(--cm-primary-rgb),0.1); backdrop-filter: blur(8px);
border: 1px solid rgba(var(--cm-primary-rgb),0.2);
font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600;
color: rgba(255,255,255,0.35); letter-spacing: 0.05em; cursor: grab; user-select: none;
}
/* Smoother animations */
.cm-toggle-track, .cm-toggle-thumb, .cm-btn-opt, .cm-tab, .cm-card, .cm-section,
.cm-file-picker, .cm-theme-btn, .cm-panic-btn, .cm-input, .cm-slider-fill {
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
.cm-card:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
.cm-btn-opt:active, .cm-tab:active { transform: scale(0.96); }
.cm-toggle input:checked ~ .cm-toggle-thumb { transform: translateX(0); }
#cm-root { transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0.3s ease; }
#cm-root:not(.visible) { opacity: 0; transform: translateX(20px) scale(0.95); visibility: hidden; pointer-events: none; }
#cm-root.visible { opacity: 1; transform: translateX(0) scale(1); visibility: visible; }
/* Disclaimer popup */
#cm-disclaimer {
position: fixed; bottom: 16px; left: 16px; z-index: 999999;
padding: 10px 14px; border-radius: 8px;
background: rgba(234, 179, 8, 0.15); backdrop-filter: blur(10px);
border: 1px solid rgba(234, 179, 8, 0.4);
font-family: 'Inter', -apple-system, sans-serif; font-size: 11px; font-weight: 500;
color: #eab308; display: flex; align-items: center; gap: 10px;
animation: cm-slide-in 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
#cm-disclaimer.hiding {
animation: cm-slide-out 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes cm-slide-in {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes cm-slide-out {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(20px); }
}
#cm-disclaimer-close {
background: none; border: none; color: #eab308; cursor: pointer;
padding: 2px; display: flex; align-items: center; justify-content: center;
border-radius: 4px; transition: all 0.2s ease;
}
#cm-disclaimer-close:hover { background: rgba(234, 179, 8, 0.2); }
#cm-disclaimer-close svg { width: 14px; height: 14px; }
`;
document.head.appendChild(style);
applyTheme(CONFIG.theme || 'crimson');
const btn = document.createElement('button');
btn.id = 'cm-toggle-btn';
btn.innerHTML = `<svg viewBox="0 0 24 24"><text x="12" y="17" text-anchor="middle" font-size="16" font-weight="bold" fill="white" font-family="Arial, sans-serif">C</text></svg>`;
document.body.appendChild(btn);
const root = document.createElement('div');
root.id = 'cm-root';
root.innerHTML = `
<div class="cm-header">
<div class="cm-title-row">
<div class="cm-logo">
<div class="cm-logo-icon">
<svg viewBox="0 0 24 24"><text x="12" y="17" text-anchor="middle" font-size="14" font-weight="bold" fill="currentColor" font-family="Arial, sans-serif">C</text></svg>
</div>
<div>
<span class="cm-title">cheatmoggle</span>
<span class="cm-version">v13.3</span>
</div>
</div>
<a href="https://discord.gg/f8GwCMHhD9" target="_blank" class="cm-discord-link">
<svg viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
Join Discord
</a>
</div>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
<div class="cm-status-row">
<span class="cm-pill active" id="cm-status-pill">ON</span>
<span class="cm-pill mode" id="cm-mode-pill">NORMAL</span>
</div>
</div>
<div class="cm-tabs">
<button class="cm-tab active" data-tab="home">Home</button>
<button class="cm-tab" data-tab="score">Score</button>
<button class="cm-tab" data-tab="effects">Effects</button>
<button class="cm-tab" data-tab="camera">Camera</button>
<button class="cm-tab" data-tab="settings">Settings</button>
</div>
</div>
<div class="cm-body">
<!-- HOME PANEL -->
<div class="cm-panel active" data-panel="home">
<div class="cm-section">
<div class="cm-section-title">System Status</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Master Switch</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-enable-toggle" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Power Status</span>
<span class="cm-value" id="cm-enabled-val" style="color: var(--cm-success)">ACTIVE</span>
</div>
<div class="cm-row">
<span class="cm-label">Match Type</span>
<span class="cm-value" id="cm-mode-val">NORMAL</span>
</div>
<div class="cm-row">
<span class="cm-label">Hook Status</span>
<span class="cm-value" id="cm-zustand-val" style="color: var(--cm-warning)">PENDING</span>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Current Rating</div>
<div class="cm-card cm-live-score">
<div class="cm-score-value" id="cm-live-score">--</div>
<div class="cm-score-tier" id="cm-live-tier">Awaiting match data...</div>
</div>
</div>
</div>
<!-- SCORE PANEL -->
<div class="cm-panel" data-panel="score">
<div class="cm-section">
<div class="cm-section-title">
<span>Score Control</span>
<label class="cm-toggle cm-section-toggle">
<input type="checkbox" id="cm-score-enabled" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-card" id="cm-score-content">
<div class="cm-row">
<span class="cm-label">Mode</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-smode="range">Range</button>
<button class="cm-btn-opt" data-smode="fixed">Fixed</button>
</div>
</div>
<div id="cm-score-fixed" style="display:none;">
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Score (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-fixed-score" min="1" max="10" step="0.1" value="9.4" style="width:60px;text-align:center;">
</div>
</div>
</div>
<div id="cm-score-range">
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Min (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-score-min" min="1" max="10" step="0.1" value="8.5" style="width:60px;text-align:center;">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Max (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-score-max" min="1" max="10" step="0.1" value="9.5" style="width:60px;text-align:center;">
</div>
</div>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">
<span>Result Settings</span>
<label class="cm-toggle cm-section-toggle">
<input type="checkbox" id="cm-result-enabled" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-card" id="cm-result-content">
<div class="cm-row">
<span class="cm-label">Type</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-fmode="fixed">Static</button>
<button class="cm-btn-opt" data-fmode="range">Dynamic</button>
</div>
</div>
<div id="cm-final-fixed">
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Target (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-final-score" min="1" max="10" step="0.1" value="9.4" style="width:60px;text-align:center;">
</div>
</div>
</div>
<div id="cm-final-range" style="display:none;">
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Lower Bound (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-final-range-min" min="1" max="10" step="0.1" value="8.5" style="width:60px;text-align:center;">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Upper Bound (1-10)</span>
<input type="number" class="cm-input cm-score-input" id="cm-final-range-max" min="1" max="10" step="0.1" value="9.7" style="width:60px;text-align:center;">
</div>
</div>
</div>
</div>
<div class="cm-preview">
<div class="cm-preview-score" id="cm-score-preview-num" style="color:#f472b6">9.6</div>
<div class="cm-preview-tier" id="cm-score-preview-tier" style="color:#f472b6">Slayer</div>
</div>
</div>
</div>
<!-- EFFECTS PANEL -->
<div class="cm-panel" data-panel="effects">
<div class="cm-section">
<div class="cm-section-title">Ambient Particles</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Activate Particles</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-particles-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Glow Aura</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-particles-glow" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Shape Style</span>
<div class="cm-shapes">
<button class="cm-shape-btn active" data-shape="circle">●</button>
<button class="cm-shape-btn" data-shape="star">★</button>
<button class="cm-shape-btn" data-shape="square">■</button>
<button class="cm-shape-btn" data-shape="heart">♥</button>
</div>
</div>
<div class="cm-row">
<span class="cm-label">Tint</span>
<div class="cm-color-row">
<input type="color" class="cm-color-input" id="cm-particles-color" value="#ffffff">
<span class="cm-label" style="font-size:11px">Spectrum</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-particles-rainbow">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Density</span>
<span class="cm-slider-value" id="cm-particles-count-val">80</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-particles-count-fill" style="width:24%"></div>
<input type="range" class="cm-slider" id="cm-particles-count" min="10" max="300" step="10" value="80">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Scale</span>
<span class="cm-slider-value" id="cm-particles-size-val">5px</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-particles-size-fill" style="width:21%"></div>
<input type="range" class="cm-slider" id="cm-particles-size" min="1" max="20" step="1" value="5">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Velocity</span>
<span class="cm-slider-value" id="cm-particles-speed-val">1.0x</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-particles-speed-fill" style="width:17%"></div>
<input type="range" class="cm-slider" id="cm-particles-speed" min="0.2" max="5.0" step="0.2" value="1.0">
</div>
</div>
</div>
</div>
</div>
<!-- CAMERA PANEL -->
<div class="cm-panel" data-panel="camera">
<div class="cm-section">
<div class="cm-section-title">Virtual Camera</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Activate Spoof</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-camspoof-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Flip Horizontal</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-cammirror-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Repeat Playback</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-camloop-toggle" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Media Type</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-src="video">Clip</button>
<button class="cm-btn-opt" data-src="image">Photo</button>
</div>
</div>
<div id="cm-src-video">
<div class="cm-row" style="margin-bottom:8px;">
<span class="cm-label">Source</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-videosrc="file">File</button>
<button class="cm-btn-opt" data-videosrc="url">URL</button>
<button class="cm-btn-opt" data-videosrc="history">History</button>
</div>
</div>
<div id="cm-video-file-src">
<div class="cm-file-picker" id="cm-video-picker">
<div class="cm-file-icon"><svg viewBox="0 0 24 24"><path d="M15 8v8H5V8h10m1-2H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4V7c0-.55-.45-1-1-1z"/></svg></div>
<span class="cm-file-name" id="cm-video-name">Choose video file...</span>
</div>
<input type="file" id="cm-video-input" accept="video/*" style="display:none">
</div>
<div id="cm-video-url-src" style="display:none;">
<input type="text" class="cm-input" id="cm-video-url" placeholder="Enter video URL..." style="width:100%;margin-bottom:8px;">
<button class="cm-btn-small" id="cm-video-url-load">Load URL</button>
</div>
<div id="cm-video-history-src" style="display:none;">
<select class="cm-select" id="cm-video-history-select" style="width:100%;">
<option value="">Select from history...</option>
</select>
</div>
<div class="cm-row" style="margin-top:8px;">
<span class="cm-label">Random Start Time</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-random-start">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
</div>
<div id="cm-src-image" style="display:none;">
<div class="cm-row" style="margin-bottom:8px;">
<span class="cm-label">Source</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-imgsrc="file">File</button>
<button class="cm-btn-opt" data-imgsrc="url">URL</button>
<button class="cm-btn-opt" data-imgsrc="history">History</button>
</div>
</div>
<div id="cm-image-file-src">
<div class="cm-file-picker" id="cm-image-picker">
<div class="cm-file-icon"><svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg></div>
<span class="cm-file-name" id="cm-image-name">Choose image file...</span>
</div>
<input type="file" id="cm-image-input" accept="image/*" style="display:none">
</div>
<div id="cm-image-url-src" style="display:none;">
<input type="text" class="cm-input" id="cm-image-url" placeholder="Enter image URL..." style="width:100%;margin-bottom:8px;">
<button class="cm-btn-small" id="cm-image-url-load">Load URL</button>
</div>
<div id="cm-image-history-src" style="display:none;">
<select class="cm-select" id="cm-image-history-select" style="width:100%;">
<option value="">Select from history...</option>
</select>
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Play Rate</span>
<span class="cm-slider-value" id="cm-camspeed-val">1.0x</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-camspeed-fill" style="width:27%"></div>
<input type="range" class="cm-slider" id="cm-camspeed" min="0.25" max="3.0" step="0.25" value="1.0">
</div>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Camera Overlay Text</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Enable Text</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-camtext-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row" style="margin-top:8px;">
<span class="cm-label">Text</span>
<input type="text" class="cm-input" id="cm-camtext-input" value="Your Text Here" style="width:140px;text-align:center;">
</div>
<div class="cm-row" style="margin-top:8px;">
<span class="cm-label">Color</span>
<input type="color" class="cm-color-input" id="cm-camtext-color" value="#ffffff">
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Font Size</span>
<span class="cm-slider-value" id="cm-camtext-size-val">24px</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-camtext-size-fill" style="width:30%"></div>
<input type="range" class="cm-slider" id="cm-camtext-size" min="12" max="72" step="2" value="24">
</div>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Audio Spoof</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Enable Audio Spoof</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-audiospoof-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row" style="margin-bottom:8px;">
<span class="cm-label">Source</span>
<div class="cm-btn-group">
<button class="cm-btn-opt active" data-audiosrc="file">File</button>
<button class="cm-btn-opt" data-audiosrc="url">URL</button>
<button class="cm-btn-opt" data-audiosrc="history">History</button>
</div>
</div>
<div id="cm-audio-file-src">
<div class="cm-file-picker" id="cm-audio-picker">
<div class="cm-file-icon"><svg viewBox="0 0 24 24"><path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/></svg></div>
<span class="cm-file-name" id="cm-audio-name">Choose audio file...</span>
</div>
<input type="file" id="cm-audio-input" accept="audio/*" style="display:none">
</div>
<div id="cm-audio-url-src" style="display:none;">
<input type="text" class="cm-input" id="cm-audio-url" placeholder="Enter audio URL..." style="width:100%;margin-bottom:8px;">
<button class="cm-btn-small" id="cm-audio-url-load">Load URL</button>
</div>
<div id="cm-audio-history-src" style="display:none;">
<select class="cm-select" id="cm-audio-history-select" style="width:100%;">
<option value="">Select from history...</option>
</select>
</div>
<div class="cm-row" style="margin-top:8px;">
<span class="cm-label">Loop Audio</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-audioloop-toggle" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Audio Speed</span>
<span class="cm-slider-value" id="cm-audiospeed-val">1.0x</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-audiospeed-fill" style="width:27%"></div>
<input type="range" class="cm-slider" id="cm-audiospeed" min="0.25" max="3.0" step="0.25" value="1.0">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Audio Volume</span>
<span class="cm-slider-value" id="cm-audiovolume-val">100%</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-audiovolume-fill" style="width:100%"></div>
<input type="range" class="cm-slider" id="cm-audiovolume" min="0" max="100" step="5" value="100">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Bass Boost</span>
<span class="cm-slider-value" id="cm-audiobass-val">0 dB</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-audiobass-fill" style="width:50%"></div>
<input type="range" class="cm-slider" id="cm-audiobass" min="-12" max="12" step="1" value="0">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Treble</span>
<span class="cm-slider-value" id="cm-audiotreble-val">0 dB</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-audiotreble-fill" style="width:50%"></div>
<input type="range" class="cm-slider" id="cm-audiotreble" min="-12" max="12" step="1" value="0">
</div>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Warmth</span>
<span class="cm-slider-value" id="cm-audiowarmth-val">0 dB</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-audiowarmth-fill" style="width:50%"></div>
<input type="range" class="cm-slider" id="cm-audiowarmth" min="-12" max="12" step="1" value="0">
</div>
</div>
<div class="cm-row">
<span class="cm-label">Status</span>
<span class="cm-value" id="cm-audio-status" style="color:var(--cm-text-muted)">Inactive</span>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Screen Effects</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Fake Ban Screen</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-ban-overlay-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Fake Loading</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-loading-overlay-toggle">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label">Current Effect</span>
<span class="cm-value" id="cm-overlay-status">None</span>
</div>
</div>
</div>
</div>
<!-- SETTINGS PANEL -->
<div class="cm-panel" data-panel="settings">
<div class="cm-section">
<div class="cm-section-title">Developer</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Console Logs</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-debug-toggle" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Hotkeys</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Open Panel</span>
<input type="text" class="cm-input" id="cm-menukey" value="h" style="width:50px;text-align:center;">
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Stream Proof</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Panic Key</span>
<input type="text" class="cm-input" id="cm-panic-key" value="p" style="width:50px;text-align:center;">
</div>
<div class="cm-row">
<span class="cm-label">Mobile: Triple-tap button</span>
<span class="cm-value" style="font-size:8px;color:var(--cm-text-muted);">to hide/show</span>
</div>
<div class="cm-row">
<button class="cm-panic-btn" id="cm-panic-now">Hide All Now</button>
</div>
<div class="cm-row" style="margin-top:6px;border-top:1px solid var(--cm-border);padding-top:6px;">
<span class="cm-label">Iframe Mode (OBS)</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-iframe-mode">
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-row">
<span class="cm-label" style="font-size:8px;color:var(--cm-text-muted);">Hides GUI from screen capture</span>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Branding</div>
<div class="cm-card">
<div class="cm-row">
<span class="cm-label">Display Badge</span>
<label class="cm-toggle">
<input type="checkbox" id="cm-wm-show" checked>
<div class="cm-toggle-track"></div>
<div class="cm-toggle-thumb"></div>
</label>
</div>
<div class="cm-slider-row">
<div class="cm-slider-header">
<span class="cm-slider-label">Visibility</span>
<span class="cm-slider-value" id="cm-wm-alpha-val">20%</span>
</div>
<div class="cm-slider-track">
<div class="cm-slider-fill" id="cm-wm-alpha-fill" style="width:20%"></div>
<input type="range" class="cm-slider" id="cm-wm-alpha" min="0" max="100" step="5" value="20">
</div>
</div>
</div>
</div>
<div class="cm-section">
<div class="cm-section-title">Appearance</div>
<div class="cm-card">
<div class="cm-theme-grid" id="cm-theme-grid"></div>
</div>
</div>
</div>
</div>
`;
document.body.appendChild(root);
// Build theme grid
const themeGrid = document.getElementById('cm-theme-grid');
Object.entries(THEMES).forEach(([key, theme]) => {
const tbtn = document.createElement('button');
tbtn.className = 'cm-theme-btn' + (key === (CONFIG.theme || 'crimson') ? ' active' : '');
tbtn.dataset.theme = key;
tbtn.innerHTML = `
<div class="cm-theme-preview" style="background: linear-gradient(135deg, ${theme.primary}, ${theme.secondary})"></div>
<div class="cm-theme-name">${theme.name}</div>
`;
tbtn.addEventListener('click', function() {
themeGrid.querySelectorAll('.cm-theme-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
applyTheme(key);
});
themeGrid.appendChild(tbtn);
});
// Toggle menu
let _btnDragged = false;
function _toggleMenu() {
if (_btnDragged) { _btnDragged = false; return; }
root.classList.toggle('visible');
}
btn.addEventListener('click', _toggleMenu);
// Toggle button drag
let _btnDragging = false, _btnDragOffX = 0, _btnDragOffY = 0, _btnStartX = 0, _btnStartY = 0;
btn.addEventListener('mousedown', function(e) {
_btnDragging = true; _btnDragged = false;
_btnStartX = e.clientX; _btnStartY = e.clientY;
const rect = btn.getBoundingClientRect();
_btnDragOffX = e.clientX - rect.left; _btnDragOffY = e.clientY - rect.top;
btn.classList.add('dragging'); e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!_btnDragging) return;
if (Math.abs(e.clientX - _btnStartX) > 5 || Math.abs(e.clientY - _btnStartY) > 5) _btnDragged = true;
btn.style.left = (e.clientX - _btnDragOffX) + 'px';
btn.style.top = (e.clientY - _btnDragOffY) + 'px';
btn.style.right = 'auto';
});
document.addEventListener('mouseup', function() {
if (_btnDragging) { _btnDragging = false; btn.classList.remove('dragging'); }
});
btn.addEventListener('touchstart', function(e) {
const touch = e.touches[0];
_btnDragging = true; _btnDragged = false;
_btnStartX = touch.clientX; _btnStartY = touch.clientY;
const rect = btn.getBoundingClientRect();
_btnDragOffX = touch.clientX - rect.left; _btnDragOffY = touch.clientY - rect.top;
btn.classList.add('dragging');
}, { passive: true });
document.addEventListener('touchmove', function(e) {
if (!_btnDragging) return;
const touch = e.touches[0];
if (Math.abs(touch.clientX - _btnStartX) > 5 || Math.abs(touch.clientY - _btnStartY) > 5) _btnDragged = true;
btn.style.left = (touch.clientX - _btnDragOffX) + 'px';
btn.style.top = (touch.clientY - _btnDragOffY) + 'px';
btn.style.right = 'auto';
}, { passive: true });
document.addEventListener('touchend', function() {
if (_btnDragging) { _btnDragging = false; btn.classList.remove('dragging'); }
});
let _menuKey = 'KeyH';
let _panicKey = 'KeyP';
let _streamHidden = false;
function toggleStreamProof() {
_streamHidden = !_streamHidden;
root.classList.toggle('stream-hidden', _streamHidden);
btn.classList.toggle('stream-hidden', _streamHidden);
log('[STREAM PROOF] ' + (_streamHidden ? 'Hidden' : 'Visible'));
}
document.addEventListener('keydown', function(e) {
if (e.code === _menuKey && !e.target.matches('input[type="text"], input[type="search"], textarea')) {
_toggleMenu();
}
if (e.code === _panicKey && !e.target.matches('input[type="text"], input[type="search"], textarea')) {
toggleStreamProof();
}
});
// Menu drag
let _menuDragging = false, _menuDragOffX = 0, _menuDragOffY = 0;
const _menuHeader = root.querySelector('.cm-header');
_menuHeader.addEventListener('mousedown', function(e) {
if (e.target.matches('input, button, label, .cm-tab, a')) return;
_menuDragging = true; root.classList.add('dragging');
const rect = root.getBoundingClientRect();
_menuDragOffX = e.clientX - rect.left; _menuDragOffY = e.clientY - rect.top;
e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!_menuDragging) return;
root.style.left = (e.clientX - _menuDragOffX) + 'px';
root.style.top = (e.clientY - _menuDragOffY) + 'px';
root.style.right = 'auto';
});
document.addEventListener('mouseup', function() {
if (_menuDragging) { _menuDragging = false; root.classList.remove('dragging'); }
});
_menuHeader.addEventListener('touchstart', function(e) {
if (e.target.matches('input, button, label, .cm-tab, a')) return;
const touch = e.touches[0];
_menuDragging = true; root.classList.add('dragging');
const rect = root.getBoundingClientRect();
_menuDragOffX = touch.clientX - rect.left; _menuDragOffY = touch.clientY - rect.top;
}, { passive: true });
document.addEventListener('touchmove', function(e) {
if (!_menuDragging) return;
const touch = e.touches[0];
root.style.left = (touch.clientX - _menuDragOffX) + 'px';
root.style.top = (touch.clientY - _menuDragOffY) + 'px';
root.style.right = 'auto';
}, { passive: true });
document.addEventListener('touchend', function() {
if (_menuDragging) { _menuDragging = false; root.classList.remove('dragging'); }
});
// Tab switching
root.querySelectorAll('.cm-tab').forEach(tab => {
tab.addEventListener('click', function() {
root.querySelectorAll('.cm-tab').forEach(t => t.classList.remove('active'));
root.querySelectorAll('.cm-panel').forEach(p => p.classList.remove('active'));
this.classList.add('active');
root.querySelector(`[data-panel="${this.dataset.tab}"]`).classList.add('active');
});
});
function updateSliderFill(slider, fill, min, max) {
const pct = ((slider.value - min) / (max - min)) * 100;
fill.style.width = pct + '%';
}
// Enable toggle
document.getElementById('cm-enable-toggle').addEventListener('change', function() {
CONFIG.enabled = this.checked;
document.getElementById('cm-enabled-val').textContent = this.checked ? 'ACTIVE' : 'OFF';
document.getElementById('cm-enabled-val').style.color = this.checked ? 'var(--cm-success)' : 'var(--cm-danger)';
document.getElementById('cm-status-pill').textContent = this.checked ? 'ON' : 'OFF';
document.getElementById('cm-status-pill').classList.toggle('active', this.checked);
});
document.getElementById('cm-score-enabled').addEventListener('change', function() {
CONFIG.scoreEnabled = this.checked;
document.getElementById('cm-score-content').classList.toggle('cm-section-disabled', !this.checked);
saveConfig();
});
document.getElementById('cm-result-enabled').addEventListener('change', function() {
CONFIG.resultEnabled = this.checked;
document.getElementById('cm-result-content').classList.toggle('cm-section-disabled', !this.checked);
saveConfig();
});
function setScoreModeUI(mode) {
CONFIG.scoreMode = mode;
document.querySelectorAll('[data-smode]').forEach(b => b.classList.toggle('active', b.dataset.smode === mode));
document.getElementById('cm-score-fixed').style.display = mode === 'fixed' ? 'block' : 'none';
document.getElementById('cm-score-range').style.display = mode === 'range' ? 'block' : 'none';
_dynamicCap = null;
saveConfig();
}
document.querySelectorAll('[data-smode]').forEach(b => {
b.addEventListener('click', function() { setScoreModeUI(this.dataset.smode); });
});
const fixedScoreInput = document.getElementById('cm-fixed-score');
fixedScoreInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.fixedScore = Math.round(val * 10000);
saveConfig();
});
const scoreMinInput = document.getElementById('cm-score-min');
scoreMinInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.scoreRangeMin = Math.round(val * 10000);
_dynamicCap = null; saveConfig();
});
const scoreMaxInput = document.getElementById('cm-score-max');
scoreMaxInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.scoreRangeMax = Math.round(val * 10000);
_dynamicCap = null; saveConfig();
});
const finalInput = document.getElementById('cm-final-score');
finalInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.myFinalScore = String(Math.round(val * 10000));
updateScorePreview(); saveConfig();
});
function setFinalModeUI(mode) {
CONFIG.finalScoreMode = mode;
document.querySelectorAll('[data-fmode]').forEach(b => b.classList.toggle('active', b.dataset.fmode === mode));
document.getElementById('cm-final-fixed').style.display = mode === 'fixed' ? 'block' : 'none';
document.getElementById('cm-final-range').style.display = mode === 'range' ? 'block' : 'none';
updateScorePreview(); saveConfig();
}
document.querySelectorAll('[data-fmode]').forEach(b => {
b.addEventListener('click', function() { setFinalModeUI(this.dataset.fmode); });
});
const finalMinInput = document.getElementById('cm-final-range-min');
finalMinInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.finalScoreRangeMin = Math.round(val * 10000);
updateScorePreview(); saveConfig();
});
const finalMaxInput = document.getElementById('cm-final-range-max');
finalMaxInput.addEventListener('input', function() {
let val = parseFloat(this.value);
if (isNaN(val)) val = 1;
val = Math.max(1, Math.min(10, val));
CONFIG.finalScoreRangeMax = Math.round(val * 10000);
updateScorePreview(); saveConfig();
});
function updateScorePreview() {
let score;
if (CONFIG.finalScoreMode === 'range') {
score = Math.round(CONFIG.finalScoreRangeMin + Math.random() * (CONFIG.finalScoreRangeMax - CONFIG.finalScoreRangeMin)) / 10000;
} else {
score = parseInt(CONFIG.myFinalScore) / 10000;
}
const tier = getTierForScore(score);
const numEl = document.getElementById('cm-score-preview-num');
const tierEl = document.getElementById('cm-score-preview-tier');
numEl.textContent = score.toFixed(1);
numEl.style.color = tier.hexColor;
numEl.style.textShadow = tier.textShadow;
tierEl.textContent = `${tier.emoji} ${tier.name}`;
tierEl.style.color = tier.hexColor;
}
updateScorePreview();
setInterval(() => { if (CONFIG.finalScoreMode === 'range') updateScorePreview(); }, 2000);
function restoreUIFromConfig() {
document.getElementById('cm-score-enabled').checked = CONFIG.scoreEnabled;
document.getElementById('cm-score-content').classList.toggle('cm-section-disabled', !CONFIG.scoreEnabled);
document.getElementById('cm-result-enabled').checked = CONFIG.resultEnabled;
document.getElementById('cm-result-content').classList.toggle('cm-section-disabled', !CONFIG.resultEnabled);
setScoreModeUI(CONFIG.scoreMode);
document.getElementById('cm-fixed-score').value = (CONFIG.fixedScore / 10000).toFixed(1);
document.getElementById('cm-score-min').value = (CONFIG.scoreRangeMin / 10000).toFixed(1);
document.getElementById('cm-score-max').value = (CONFIG.scoreRangeMax / 10000).toFixed(1);
setFinalModeUI(CONFIG.finalScoreMode);
document.getElementById('cm-final-score').value = (parseInt(CONFIG.myFinalScore) / 10000).toFixed(1);
document.getElementById('cm-final-range-min').value = (CONFIG.finalScoreRangeMin / 10000).toFixed(1);
document.getElementById('cm-final-range-max').value = (CONFIG.finalScoreRangeMax / 10000).toFixed(1);
if (CONFIG.theme && THEMES[CONFIG.theme]) applyTheme(CONFIG.theme);
}
restoreUIFromConfig();
// Menu keybind
const menuKeyInput = document.getElementById('cm-menukey');
let _menuKeyListening = false;
menuKeyInput.addEventListener('focus', function() {
_menuKeyListening = true; this.value = 'press';
this.style.borderColor = 'var(--cm-primary)';
});
menuKeyInput.addEventListener('keydown', function(e) {
if (!_menuKeyListening) return;
e.preventDefault();
_menuKey = e.code;
this.value = e.key === ' ' ? 'Space' : e.key;
this.style.borderColor = 'var(--cm-success)';
_menuKeyListening = false; this.blur();
});
// Panic keybind
const panicKeyInput = document.getElementById('cm-panic-key');
let _panicKeyListening = false;
panicKeyInput.addEventListener('focus', function() {
_panicKeyListening = true; this.value = 'press';
this.style.borderColor = 'var(--cm-primary)';
});
panicKeyInput.addEventListener('keydown', function(e) {
if (!_panicKeyListening) return;
e.preventDefault();
_panicKey = e.code;
this.value = e.key === ' ' ? 'Space' : e.key;
this.style.borderColor = 'var(--cm-success)';
_panicKeyListening = false; this.blur();
});
document.getElementById('cm-panic-now').addEventListener('click', toggleStreamProof);
// Mobile triple-tap
let _tripleTapCount = 0, _tripleTapTimer = null;
btn.addEventListener('touchend', function(e) {
if (_btnDragged) return;
_tripleTapCount++;
if (_tripleTapCount === 1) {
_tripleTapTimer = setTimeout(() => { _tripleTapCount = 0; }, 500);
}
if (_tripleTapCount === 3) {
clearTimeout(_tripleTapTimer); _tripleTapCount = 0;
toggleStreamProof(); e.preventDefault();
}
});
// Iframe mode
let _iframeMode = false, _iframeWrapper = null;
function enableIframeMode() {
if (_iframeWrapper) return;
_iframeWrapper = document.createElement('div');
_iframeWrapper.id = 'cm-iframe-wrapper';
_iframeWrapper.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:999996;';
const iframe = document.createElement('iframe');
iframe.id = 'cm-stream-iframe';
iframe.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;border:none;background:transparent;pointer-events:none;';
iframe.setAttribute('allowtransparency', 'true');
_iframeWrapper.appendChild(iframe);
document.body.appendChild(_iframeWrapper);
setTimeout(() => {
try {
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write('<!DOCTYPE html><html><head><style>body{margin:0;background:transparent;overflow:hidden;}</style></head><body></body></html>');
iframeDoc.close();
const styles = document.createElement('style');
styles.textContent = Array.from(document.styleSheets).map(sheet => {
try { return Array.from(sheet.cssRules).map(r => r.cssText).join('\n'); } catch(e) { return ''; }
}).join('\n');
iframeDoc.head.appendChild(styles);
btn.style.pointerEvents = 'auto';
root.style.pointerEvents = 'auto';
iframeDoc.body.appendChild(btn);
iframeDoc.body.appendChild(root);
iframe.style.pointerEvents = 'auto';
iframeDoc.addEventListener('keydown', function(e) {
if (e.code === _menuKey) _toggleMenu();
if (e.code === _panicKey) toggleStreamProof();
});
log('[IFRAME MODE] Enabled');
} catch(err) {
log('[IFRAME MODE] Error:', err);
disableIframeMode();
}
}, 100);
}
function disableIframeMode() {
if (!_iframeWrapper) return;
try {
const iframe = document.getElementById('cm-stream-iframe');
if (iframe) {
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
if (iframeDoc.body.contains(btn)) document.body.appendChild(btn);
if (iframeDoc.body.contains(root)) document.body.appendChild(root);
}
} catch(e) {}
btn.style.position = ''; btn.style.top = ''; btn.style.left = ''; btn.style.right = '';
root.style.position = ''; root.style.top = ''; root.style.left = ''; root.style.right = '';
_iframeWrapper.remove(); _iframeWrapper = null;
log('[IFRAME MODE] Disabled');
}
document.getElementById('cm-iframe-mode').addEventListener('change', function() {
_iframeMode = this.checked;
if (_iframeMode) enableIframeMode(); else disableIframeMode();
});
document.getElementById('cm-debug-toggle').addEventListener('change', function() {
CONFIG.debug = this.checked;
});
// Watermark
const _wm = document.createElement('div');
_wm.id = 'cm-watermark';
_wm.textContent = 'cheatmoggle v13.3';
document.body.appendChild(_wm);
// Disclaimer popup
const _disclaimer = document.createElement('div');
_disclaimer.id = 'cm-disclaimer';
_disclaimer.innerHTML = `
<span>⚠️ This script only works for ranked mode</span>
<button id="cm-disclaimer-close">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
`;
document.body.appendChild(_disclaimer);
document.getElementById('cm-disclaimer-close').addEventListener('click', function() {
_disclaimer.classList.add('hiding');
setTimeout(() => _disclaimer.remove(), 300);
});
function applyWmStyle() { _wm.style.opacity = CONFIG.wmAlpha / 100; }
applyWmStyle();
document.getElementById('cm-wm-show').addEventListener('change', function() {
_wm.style.display = this.checked ? 'block' : 'none';
});
const wmAlphaSlider = document.getElementById('cm-wm-alpha');
const wmAlphaFill = document.getElementById('cm-wm-alpha-fill');
wmAlphaSlider.addEventListener('input', function() {
CONFIG.wmAlpha = parseInt(this.value);
document.getElementById('cm-wm-alpha-val').textContent = this.value + '%';
updateSliderFill(this, wmAlphaFill, 0, 100);
applyWmStyle();
});
// Watermark drag
let _wmDragging = false, _wmDragOffX = 0, _wmDragOffY = 0;
_wm.addEventListener('mousedown', function(e) {
_wmDragging = true;
_wmDragOffX = e.clientX - _wm.getBoundingClientRect().left;
_wmDragOffY = e.clientY - _wm.getBoundingClientRect().top;
_wm.style.cursor = 'grabbing'; e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!_wmDragging) return;
_wm.style.left = (e.clientX - _wmDragOffX) + 'px';
_wm.style.top = (e.clientY - _wmDragOffY) + 'px';
_wm.style.bottom = 'auto'; _wm.style.right = 'auto';
});
document.addEventListener('mouseup', function() {
if (_wmDragging) { _wmDragging = false; _wm.style.cursor = 'grab'; }
});
// Live status updater
setInterval(() => {
document.getElementById('cm-mode-pill').textContent = _isRanked ? 'RANKED' : 'NORMAL';
document.getElementById('cm-mode-val').textContent = _isRanked ? 'RANKED' : 'NORMAL';
if (_lastSpoofedScore !== null) {
const tier = getTierForScore(_lastSpoofedScore);
const liveScore = document.getElementById('cm-live-score');
const liveTier = document.getElementById('cm-live-tier');
if (liveScore) {
liveScore.textContent = _lastSpoofedScore.toFixed(2);
liveScore.style.color = tier.hexColor;
liveScore.style.textShadow = tier.textShadow;
}
if (liveTier) {
liveTier.textContent = `${tier.emoji} ${tier.name}`;
liveTier.style.color = tier.hexColor;
}
}
}, 200);
// ── CAMERA SPOOF ───────────────────────────────────────────────────
let _camSrcType = 'video';
let _camVideoFile = null;
let _camImageFile = null;
let _camMirror = false;
let _camLoop = true;
let _camSpeed = 1.0;
let _camVideoEl = null;
let _camCanvasEl = null;
let _origAddTrack = null;
let _camSrcObjPatch = null;
let _camDrawRAF = null;
let _camImageEl = null;
// Camera text overlay settings
let _camTextEnabled = false;
let _camTextContent = 'Your Text Here';
let _camTextColor = '#ffffff';
let _camTextSize = 24;
window._mogPCs = window._mogPCs || [];
const _OrigPC2 = window.RTCPeerConnection;
window.RTCPeerConnection = function(...args) {
const pc = new _OrigPC2(...args);
window._mogPCs.push(pc);
pc.addEventListener('connectionstatechange', () => {
if (pc.connectionState === 'closed') {
const idx = window._mogPCs.indexOf(pc);
if (idx > -1) window._mogPCs.splice(idx, 1);
}
});
return pc;
};
Object.setPrototypeOf(window.RTCPeerConnection, _OrigPC2);
window.RTCPeerConnection.prototype = _OrigPC2.prototype;
document.querySelectorAll('[data-src]').forEach(b => {
b.addEventListener('click', function() {
_camSrcType = this.dataset.src;
document.querySelectorAll('[data-src]').forEach(x => x.classList.toggle('active', x.dataset.src === _camSrcType));
document.getElementById('cm-src-video').style.display = _camSrcType === 'video' ? 'block' : 'none';
document.getElementById('cm-src-image').style.display = _camSrcType === 'image' ? 'block' : 'none';
});
});
// File history storage
let _videoHistory = JSON.parse(localStorage.getItem('cm_video_history') || '[]');
let _imageHistory = JSON.parse(localStorage.getItem('cm_image_history') || '[]');
let _audioHistory = JSON.parse(localStorage.getItem('cm_audio_history') || '[]');
let _camVideoUrl = null;
let _camImageUrl = null;
let _audioUrl = null;
function addToHistory(type, name, url) {
let history = type === 'video' ? _videoHistory : type === 'image' ? _imageHistory : _audioHistory;
const existing = history.findIndex(h => h.name === name || h.url === url);
if (existing !== -1) history.splice(existing, 1);
history.unshift({ name, url, date: Date.now() });
if (history.length > 10) history.pop();
localStorage.setItem('cm_' + type + '_history', JSON.stringify(history));
updateHistorySelect(type);
}
function updateHistorySelect(type) {
const history = type === 'video' ? _videoHistory : type === 'image' ? _imageHistory : _audioHistory;
const select = document.getElementById('cm-' + type + '-history-select');
if (!select) return;
select.innerHTML = '<option value="">Select from history...</option>';
history.forEach((item, i) => {
const opt = document.createElement('option');
opt.value = i;
opt.textContent = item.name || item.url.substring(0, 40) + '...';
select.appendChild(opt);
});
}
// Video source type switching
document.querySelectorAll('[data-videosrc]').forEach(btn => {
btn.addEventListener('click', function() {
const srcType = this.dataset.videosrc;
document.querySelectorAll('[data-videosrc]').forEach(x => x.classList.toggle('active', x.dataset.videosrc === srcType));
document.getElementById('cm-video-file-src').style.display = srcType === 'file' ? 'block' : 'none';
document.getElementById('cm-video-url-src').style.display = srcType === 'url' ? 'block' : 'none';
document.getElementById('cm-video-history-src').style.display = srcType === 'history' ? 'block' : 'none';
});
});
// Image source type switching
document.querySelectorAll('[data-imgsrc]').forEach(btn => {
btn.addEventListener('click', function() {
const srcType = this.dataset.imgsrc;
document.querySelectorAll('[data-imgsrc]').forEach(x => x.classList.toggle('active', x.dataset.imgsrc === srcType));
document.getElementById('cm-image-file-src').style.display = srcType === 'file' ? 'block' : 'none';
document.getElementById('cm-image-url-src').style.display = srcType === 'url' ? 'block' : 'none';
document.getElementById('cm-image-history-src').style.display = srcType === 'history' ? 'block' : 'none';
});
});
// Audio source type switching
document.querySelectorAll('[data-audiosrc]').forEach(btn => {
btn.addEventListener('click', function() {
const srcType = this.dataset.audiosrc;
document.querySelectorAll('[data-audiosrc]').forEach(x => x.classList.toggle('active', x.dataset.audiosrc === srcType));
document.getElementById('cm-audio-file-src').style.display = srcType === 'file' ? 'block' : 'none';
document.getElementById('cm-audio-url-src').style.display = srcType === 'url' ? 'block' : 'none';
document.getElementById('cm-audio-history-src').style.display = srcType === 'history' ? 'block' : 'none';
});
});
document.getElementById('cm-video-picker').addEventListener('click', () => document.getElementById('cm-video-input').click());
document.getElementById('cm-video-input').addEventListener('change', function() {
if (this.files[0]) {
_camVideoFile = this.files[0];
_camVideoUrl = null;
document.getElementById('cm-video-name').textContent = this.files[0].name;
document.getElementById('cm-video-name').classList.add('selected');
addToHistory('video', this.files[0].name, URL.createObjectURL(this.files[0]));
}
});
// Video URL loading
document.getElementById('cm-video-url-load').addEventListener('click', function() {
const url = document.getElementById('cm-video-url').value.trim();
if (url) {
_camVideoUrl = url;
_camVideoFile = null;
document.getElementById('cm-video-name').textContent = 'URL: ' + url.substring(0, 30) + '...';
document.getElementById('cm-video-name').classList.add('selected');
addToHistory('video', 'URL: ' + url.substring(0, 30), url);
log('[CAM] Video URL set:', url);
}
});
// Video history selection
document.getElementById('cm-video-history-select').addEventListener('change', function() {
if (this.value !== '') {
const item = _videoHistory[parseInt(this.value)];
if (item) {
_camVideoUrl = item.url;
_camVideoFile = null;
document.getElementById('cm-video-name').textContent = item.name;
document.getElementById('cm-video-name').classList.add('selected');
log('[CAM] Video loaded from history:', item.name);
}
}
});
// Image URL loading
document.getElementById('cm-image-url-load').addEventListener('click', function() {
const url = document.getElementById('cm-image-url').value.trim();
if (url) {
_camImageUrl = url;
_camImageFile = null;
document.getElementById('cm-image-name').textContent = 'URL: ' + url.substring(0, 30) + '...';
document.getElementById('cm-image-name').classList.add('selected');
addToHistory('image', 'URL: ' + url.substring(0, 30), url);
log('[CAM] Image URL set:', url);
}
});
// Image history selection
document.getElementById('cm-image-history-select').addEventListener('change', function() {
if (this.value !== '') {
const item = _imageHistory[parseInt(this.value)];
if (item) {
_camImageUrl = item.url;
_camImageFile = null;
document.getElementById('cm-image-name').textContent = item.name;
document.getElementById('cm-image-name').classList.add('selected');
log('[CAM] Image loaded from history:', item.name);
}
}
});
// Audio URL loading
document.getElementById('cm-audio-url-load').addEventListener('click', function() {
const url = document.getElementById('cm-audio-url').value.trim();
if (url) {
_audioUrl = url;
_audioFile = null;
document.getElementById('cm-audio-name').textContent = 'URL: ' + url.substring(0, 30) + '...';
document.getElementById('cm-audio-name').classList.add('selected');
addToHistory('audio', 'URL: ' + url.substring(0, 30), url);
log('[AUDIO] Audio URL set:', url);
if (_audioSpoofActive) { stopAudioSpoof(); startAudioSpoof(); }
}
});
// Audio history selection
document.getElementById('cm-audio-history-select').addEventListener('change', function() {
if (this.value !== '') {
const item = _audioHistory[parseInt(this.value)];
if (item) {
_audioUrl = item.url;
_audioFile = null;
document.getElementById('cm-audio-name').textContent = item.name;
document.getElementById('cm-audio-name').classList.add('selected');
log('[AUDIO] Audio loaded from history:', item.name);
if (_audioSpoofActive) { stopAudioSpoof(); startAudioSpoof(); }
}
}
});
// Initialize history selects
updateHistorySelect('video');
updateHistorySelect('image');
updateHistorySelect('audio');
let _camRandomStart = false;
document.getElementById('cm-random-start').addEventListener('change', function() { _camRandomStart = this.checked; });
document.getElementById('cm-image-picker').addEventListener('click', () => document.getElementById('cm-image-input').click());
document.getElementById('cm-image-input').addEventListener('change', function() {
if (this.files[0]) {
_camImageFile = this.files[0];
_camImageUrl = null;
document.getElementById('cm-image-name').textContent = this.files[0].name;
document.getElementById('cm-image-name').classList.add('selected');
addToHistory('image', this.files[0].name, URL.createObjectURL(this.files[0]));
}
});
document.getElementById('cm-camloop-toggle').addEventListener('change', function() {
_camLoop = this.checked;
if (_camVideoEl) _camVideoEl.loop = _camLoop;
});
const camSpeedSlider = document.getElementById('cm-camspeed');
const camSpeedFill = document.getElementById('cm-camspeed-fill');
camSpeedSlider.addEventListener('input', function() {
_camSpeed = parseFloat(this.value);
document.getElementById('cm-camspeed-val').textContent = _camSpeed.toFixed(2) + 'x';
updateSliderFill(this, camSpeedFill, 0.25, 3.0);
if (_camVideoEl) _camVideoEl.playbackRate = _camSpeed;
});
document.getElementById('cm-cammirror-toggle').addEventListener('change', function() { _camMirror = this.checked; });
// Camera text overlay handlers
document.getElementById('cm-camtext-toggle').addEventListener('change', function() {
_camTextEnabled = this.checked;
});
document.getElementById('cm-camtext-input').addEventListener('input', function() {
_camTextContent = this.value;
});
document.getElementById('cm-camtext-color').addEventListener('input', function() {
_camTextColor = this.value;
});
const camTextSizeSlider = document.getElementById('cm-camtext-size');
const camTextSizeFill = document.getElementById('cm-camtext-size-fill');
camTextSizeSlider.addEventListener('input', function() {
_camTextSize = parseInt(this.value);
document.getElementById('cm-camtext-size-val').textContent = _camTextSize + 'px';
updateSliderFill(this, camTextSizeFill, 12, 72);
});
function buildFakeStream() {
if (_camDrawRAF) cancelAnimationFrame(_camDrawRAF);
if (_camVideoEl) { _camVideoEl.pause(); _camVideoEl.src = ''; }
_camCanvasEl = document.createElement('canvas');
_camCanvasEl.width = 640; _camCanvasEl.height = 480;
const ctx = _camCanvasEl.getContext('2d');
function drawLoop() {
if (!_camSpoofActive) { _camDrawRAF = null; return; }
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 640, 480);
ctx.save();
if (_camMirror) { ctx.translate(640, 0); ctx.scale(-1, 1); }
if (_camSrcType === 'video' && _camVideoEl && _camVideoEl.readyState >= 2) {
ctx.drawImage(_camVideoEl, 0, 0, 640, 480);
} else if (_camSrcType === 'image' && _camImageEl && _camImageEl.complete) {
ctx.drawImage(_camImageEl, 0, 0, 640, 480);
}
ctx.restore();
// Draw text overlay at bottom (after restore so it's not mirrored)
if (_camTextEnabled && _camTextContent) {
ctx.save();
ctx.font = 'bold ' + _camTextSize + 'px Arial, sans-serif';
ctx.fillStyle = _camTextColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.shadowColor = 'rgba(0,0,0,0.8)';
ctx.shadowBlur = 6;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.fillText(_camTextContent, 320, 465);
ctx.restore();
}
_camDrawRAF = requestAnimationFrame(drawLoop);
}
if (_camSrcType === 'video' && (_camVideoFile || _camVideoUrl)) {
_camVideoEl = document.createElement('video');
_camVideoEl.src = _camVideoFile ? URL.createObjectURL(_camVideoFile) : _camVideoUrl;
_camVideoEl.loop = _camLoop;
_camVideoEl.muted = true;
_camVideoEl.playsInline = true;
_camVideoEl.crossOrigin = 'anonymous';
_camVideoEl.playbackRate = _camSpeed;
if (_camRandomStart) {
_camVideoEl.addEventListener('loadedmetadata', function() {
if (_camVideoEl.duration > 0) {
const t = Math.random() * _camVideoEl.duration;
_camVideoEl.currentTime = t;
log('[CAM] Random start at:', t.toFixed(2) + 's');
}
}, { once: true });
}
_camVideoEl.play().catch(() => {});
drawLoop();
} else if (_camSrcType === 'image' && (_camImageFile || _camImageUrl)) {
_camImageEl = new Image();
_camImageEl.crossOrigin = 'anonymous';
_camImageEl.src = _camImageFile ? URL.createObjectURL(_camImageFile) : _camImageUrl;
_camImageEl.onload = () => drawLoop();
drawLoop();
} else {
log('[CAM] No source selected');
return null;
}
return _camCanvasEl.captureStream(30);
}
function startCamSpoof() {
const fakeStream = buildFakeStream();
if (!fakeStream) return;
_camStream = fakeStream;
const _srcObjDesc = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
if (!_camSrcObjPatch) {
_camSrcObjPatch = function(stream) {
if (this.classList?.contains('scanner-video') && stream && _camSpoofActive && _camStream) {
_srcObjDesc.set.call(this, _camStream); return;
}
_srcObjDesc.set.call(this, stream);
};
Object.defineProperty(HTMLMediaElement.prototype, 'srcObject', {
get() { return _srcObjDesc.get.call(this); },
set: _camSrcObjPatch,
configurable: true
});
}
const scannerVid = document.querySelector('video.scanner-video');
if (scannerVid) scannerVid.srcObject = _camStream;
if (!_origAddTrack) {
_origAddTrack = RTCPeerConnection.prototype.addTrack;
RTCPeerConnection.prototype.addTrack = function(track, ...streams) {
if (track.kind === 'video' && _camSpoofActive && _camStream) {
const fakeTrack = _camStream.getVideoTracks()[0];
if (fakeTrack) return _origAddTrack.call(this, fakeTrack, ...streams);
}
return _origAddTrack.call(this, track, ...streams);
};
}
try {
const fakeTrack = _camStream.getVideoTracks()[0];
if (fakeTrack && window._mogPCs) {
for (const pc of window._mogPCs) {
pc.getSenders().forEach(sender => {
if (sender.track?.kind === 'video') sender.replaceTrack(fakeTrack).catch(() => {});
});
}
}
} catch(e) {}
}
function stopCamSpoof() {
if (_camDrawRAF) { cancelAnimationFrame(_camDrawRAF); _camDrawRAF = null; }
if (_camVideoEl) { _camVideoEl.pause(); _camVideoEl.src = ''; _camVideoEl = null; }
if (_camImageEl) _camImageEl = null;
if (_camStream) { _camStream.getTracks().forEach(t => t.stop()); _camStream = null; }
_trueOriginalGetUserMedia({ video: true }).then(realStream => {
const realTrack = realStream.getVideoTracks()[0];
const scannerVid = document.querySelector('video.scanner-video');
if (scannerVid) scannerVid.srcObject = realStream;
if (realTrack && window._mogPCs) {
for (const pc of window._mogPCs) {
pc.getSenders().forEach(sender => {
if (sender.track?.kind === 'video') sender.replaceTrack(realTrack).catch(() => {});
});
}
}
}).catch(() => {});
}
document.getElementById('cm-camspoof-toggle').addEventListener('change', function() {
_camSpoofActive = this.checked;
if (_camSpoofActive) startCamSpoof(); else stopCamSpoof();
});
// ── AUDIO SPOOF ────────────────────────────────────────────────────
let _audioSpoofActive = false;
let _audioFile = null;
let _audioEl = null;
let _audioLoop = true;
let _audioSpeed = 1.0;
let _audioVolume = 1.0;
let _audioStream = null;
let _audioContext = null;
let _audioSource = null;
let _audioDestination = null;
let _audioBassFilter = null;
let _audioTrebleFilter = null;
let _audioWarmthFilter = null;
let _audioBass = 0;
let _audioTreble = 0;
let _audioWarmth = 0;
document.getElementById('cm-audio-picker').addEventListener('click', () => document.getElementById('cm-audio-input').click());
document.getElementById('cm-audio-input').addEventListener('change', function() {
if (this.files[0]) {
_audioFile = this.files[0];
_audioUrl = null;
document.getElementById('cm-audio-name').textContent = this.files[0].name;
document.getElementById('cm-audio-name').classList.add('selected');
addToHistory('audio', this.files[0].name, URL.createObjectURL(this.files[0]));
if (_audioSpoofActive) {
stopAudioSpoof();
startAudioSpoof();
}
}
});
document.getElementById('cm-audioloop-toggle').addEventListener('change', function() {
_audioLoop = this.checked;
if (_audioEl) _audioEl.loop = _audioLoop;
});
const audioSpeedSlider = document.getElementById('cm-audiospeed');
const audioSpeedFill = document.getElementById('cm-audiospeed-fill');
audioSpeedSlider.addEventListener('input', function() {
_audioSpeed = parseFloat(this.value);
document.getElementById('cm-audiospeed-val').textContent = _audioSpeed.toFixed(2) + 'x';
updateSliderFill(this, audioSpeedFill, 0.25, 3.0);
if (_audioEl) _audioEl.playbackRate = _audioSpeed;
});
const audioVolumeSlider = document.getElementById('cm-audiovolume');
const audioVolumeFill = document.getElementById('cm-audiovolume-fill');
audioVolumeSlider.addEventListener('input', function() {
_audioVolume = parseInt(this.value) / 100;
document.getElementById('cm-audiovolume-val').textContent = this.value + '%';
updateSliderFill(this, audioVolumeFill, 0, 100);
if (_audioEl) _audioEl.volume = _audioVolume;
});
const audioBassSlider = document.getElementById('cm-audiobass');
const audioBassFill = document.getElementById('cm-audiobass-fill');
audioBassSlider.addEventListener('input', function() {
_audioBass = parseInt(this.value);
document.getElementById('cm-audiobass-val').textContent = _audioBass + ' dB';
updateSliderFill(this, audioBassFill, -12, 12);
if (_audioBassFilter) _audioBassFilter.gain.value = _audioBass;
});
const audioTrebleSlider = document.getElementById('cm-audiotreble');
const audioTrebleFill = document.getElementById('cm-audiotreble-fill');
audioTrebleSlider.addEventListener('input', function() {
_audioTreble = parseInt(this.value);
document.getElementById('cm-audiotreble-val').textContent = _audioTreble + ' dB';
updateSliderFill(this, audioTrebleFill, -12, 12);
if (_audioTrebleFilter) _audioTrebleFilter.gain.value = _audioTreble;
});
const audioWarmthSlider = document.getElementById('cm-audiowarmth');
const audioWarmthFill = document.getElementById('cm-audiowarmth-fill');
audioWarmthSlider.addEventListener('input', function() {
_audioWarmth = parseInt(this.value);
document.getElementById('cm-audiowarmth-val').textContent = _audioWarmth + ' dB';
updateSliderFill(this, audioWarmthFill, -12, 12);
if (_audioWarmthFilter) _audioWarmthFilter.gain.value = _audioWarmth;
});
function startAudioSpoof() {
if (!_audioFile && !_audioUrl) {
document.getElementById('cm-audio-status').textContent = 'No file selected';
document.getElementById('cm-audio-status').style.color = 'var(--cm-warning)';
return;
}
try {
_audioEl = document.createElement('audio');
_audioEl.src = _audioFile ? URL.createObjectURL(_audioFile) : _audioUrl;
_audioEl.crossOrigin = 'anonymous';
_audioEl.loop = _audioLoop;
_audioEl.playbackRate = _audioSpeed;
_audioEl.volume = _audioVolume;
_audioContext = new (window.AudioContext || window.webkitAudioContext)();
_audioSource = _audioContext.createMediaElementSource(_audioEl);
// Create EQ filters
// Bass filter (lowshelf at 150Hz)
_audioBassFilter = _audioContext.createBiquadFilter();
_audioBassFilter.type = 'lowshelf';
_audioBassFilter.frequency.value = 150;
_audioBassFilter.gain.value = _audioBass;
// Treble filter (highshelf at 4000Hz)
_audioTrebleFilter = _audioContext.createBiquadFilter();
_audioTrebleFilter.type = 'highshelf';
_audioTrebleFilter.frequency.value = 4000;
_audioTrebleFilter.gain.value = _audioTreble;
// Warmth filter (peaking at 500Hz for mid warmth)
_audioWarmthFilter = _audioContext.createBiquadFilter();
_audioWarmthFilter.type = 'peaking';
_audioWarmthFilter.frequency.value = 500;
_audioWarmthFilter.Q.value = 1;
_audioWarmthFilter.gain.value = _audioWarmth;
_audioDestination = _audioContext.createMediaStreamDestination();
// Chain: source -> bass -> warmth -> treble -> destination
_audioSource.connect(_audioBassFilter);
_audioBassFilter.connect(_audioWarmthFilter);
_audioWarmthFilter.connect(_audioTrebleFilter);
_audioTrebleFilter.connect(_audioDestination);
_audioTrebleFilter.connect(_audioContext.destination); // also play locally for feedback
_audioStream = _audioDestination.stream;
_audioEl.play().catch(e => {
log('[AUDIO SPOOF] Play error:', e);
});
document.getElementById('cm-audio-status').textContent = 'Active';
document.getElementById('cm-audio-status').style.color = 'var(--cm-success)';
log('[AUDIO SPOOF] Started with file:', _audioFile.name);
} catch(e) {
log('[AUDIO SPOOF] Error:', e);
document.getElementById('cm-audio-status').textContent = 'Error';
document.getElementById('cm-audio-status').style.color = 'var(--cm-danger)';
}
}
function stopAudioSpoof() {
if (_audioEl) {
_audioEl.pause();
_audioEl.src = '';
_audioEl = null;
}
if (_audioContext) {
_audioContext.close().catch(() => {});
_audioContext = null;
}
_audioSource = null;
_audioDestination = null;
_audioBassFilter = null;
_audioTrebleFilter = null;
_audioWarmthFilter = null;
_audioStream = null;
document.getElementById('cm-audio-status').textContent = 'Inactive';
document.getElementById('cm-audio-status').style.color = 'var(--cm-text-muted)';
log('[AUDIO SPOOF] Stopped');
}
document.getElementById('cm-audiospoof-toggle').addEventListener('change', function() {
_audioSpoofActive = this.checked;
if (_audioSpoofActive) startAudioSpoof(); else stopAudioSpoof();
});
// Patch getUserMedia to inject spoofed audio
const _origGetUserMediaForAudio = navigator.mediaDevices.getUserMedia;
navigator.mediaDevices.getUserMedia = async function(constraints) {
if (_audioSpoofActive && _audioStream && constraints && constraints.audio) {
log('[AUDIO SPOOF] Intercepting getUserMedia - injecting spoofed audio');
const realStream = await _trueOriginalGetUserMedia(constraints);
if (constraints.video) {
// Combine real video with spoofed audio
const combinedTracks = [
...realStream.getVideoTracks(),
..._audioStream.getAudioTracks()
];
return new MediaStream(combinedTracks);
} else {
// Audio only request
return _audioStream;
}
}
return _origGetUserMediaForAudio.call(navigator.mediaDevices, constraints);
};
// Cam spoof enforcer
setInterval(() => {
if (!_camSpoofActive || !_camStream) return;
const scannerVid = document.querySelector('video.scanner-video');
if (scannerVid && scannerVid.srcObject !== _camStream) {
log('[CAM SPOOF] Re-applying spoof to scanner-video');
scannerVid.srcObject = _camStream;
}
const fakeTrack = _camStream.getVideoTracks()[0];
if (fakeTrack && window._mogPCs) {
for (const pc of window._mogPCs) {
try {
pc.getSenders().forEach(sender => {
if (sender.track?.kind === 'video' && sender.track !== fakeTrack) {
sender.replaceTrack(fakeTrack).catch(() => {});
}
});
} catch(e) {}
}
}
}, 500);
// Watch for new scanner-video
const camSpoofObserver = new MutationObserver((mutations) => {
if (!_camSpoofActive || !_camStream) return;
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1) {
const sv = node.classList?.contains('scanner-video') ? node : node.querySelector?.('video.scanner-video');
if (sv && sv.srcObject !== _camStream) {
log('[CAM SPOOF] New scanner-video detected, applying spoof');
sv.srcObject = _camStream;
}
}
}
}
});
camSpoofObserver.observe(document.body, { childList: true, subtree: true });
// ── PARTICLE ENGINE ────────────────────────────────────────────────
const _particleCfg = {
active: false, count: 80, size: 5, speed: 1.0, drift: 0.5,
opacity: 70, color: '#ffffff', rainbow: false, shape: 'circle', glow: true, wobble: true
};
let _particleCanvas = null, _particleCtx = null, _particleRAF = null, _particles = [];
function _makeParticle() {
return {
x: Math.random() * window.innerWidth,
y: -20 - Math.random() * window.innerHeight,
r: (_particleCfg.size * 0.5) + Math.random() * _particleCfg.size * 0.8,
vy: (1.0 + Math.random() * 1.5) * _particleCfg.speed,
vx: (Math.random() - 0.5) * _particleCfg.drift,
wobblePhase: Math.random() * Math.PI * 2,
wobbleSpeed: 0.01 + Math.random() * 0.03,
wobbleAmp: 0.5 + Math.random() * 2.0,
hue: Math.random() * 360,
alpha: 0.3 + Math.random() * 0.7
};
}
function _drawShape(ctx, p, color) {
const s = p.r;
ctx.fillStyle = color; ctx.strokeStyle = color;
if (_particleCfg.glow) { ctx.shadowColor = color; ctx.shadowBlur = s * 2.5; }
else { ctx.shadowBlur = 0; }
ctx.beginPath();
switch (_particleCfg.shape) {
case 'circle': ctx.arc(p.x, p.y, s, 0, Math.PI * 2); ctx.fill(); break;
case 'square': ctx.fillRect(p.x - s, p.y - s, s * 2, s * 2); break;
case 'star': {
const spikes = 5, outer = s, inner = s * 0.45;
let rot = (Math.PI / 2) * 3;
const step = Math.PI / spikes;
ctx.moveTo(p.x, p.y - outer);
for (let i = 0; i < spikes; i++) {
ctx.lineTo(p.x + Math.cos(rot) * outer, p.y + Math.sin(rot) * outer); rot += step;
ctx.lineTo(p.x + Math.cos(rot) * inner, p.y + Math.sin(rot) * inner); rot += step;
}
ctx.lineTo(p.x, p.y - outer); ctx.fill(); break;
}
case 'heart': {
const hs = s * 0.9;
ctx.moveTo(p.x, p.y + hs * 0.6);
ctx.bezierCurveTo(p.x - hs * 1.2, p.y - hs * 0.4, p.x - hs * 2.2, p.y + hs * 0.6, p.x, p.y + hs * 1.8);
ctx.bezierCurveTo(p.x + hs * 2.2, p.y + hs * 0.6, p.x + hs * 1.2, p.y - hs * 0.4, p.x, p.y + hs * 0.6);
ctx.fill(); break;
}
}
}
function _particleLoop() {
if (!_particleCfg.active) return;
const W = window.innerWidth, H = window.innerHeight;
if (_particleCanvas.width !== W) _particleCanvas.width = W;
if (_particleCanvas.height !== H) _particleCanvas.height = H;
_particleCtx.clearRect(0, 0, W, H);
while (_particles.length < _particleCfg.count) _particles.push(_makeParticle());
while (_particles.length > _particleCfg.count) _particles.pop();
for (const p of _particles) {
p.wobblePhase += p.wobbleSpeed;
if (_particleCfg.wobble) p.x += Math.sin(p.wobblePhase) * p.wobbleAmp;
p.x += p.vx; p.y += p.vy;
if (p.y > H + 30) {
p.y = -20; p.x = Math.random() * W;
p.vx = (Math.random() - 0.5) * _particleCfg.drift;
p.hue = Math.random() * 360;
}
const baseAlpha = (_particleCfg.opacity / 100) * p.alpha;
let color;
if (_particleCfg.rainbow) {
color = `hsla(${p.hue},100%,70%,${baseAlpha})`;
p.hue = (p.hue + 0.3) % 360;
} else {
const hex = _particleCfg.color;
const r = parseInt(hex.slice(1,3),16);
const g = parseInt(hex.slice(3,5),16);
const b = parseInt(hex.slice(5,7),16);
color = `rgba(${r},${g},${b},${baseAlpha})`;
}
_particleCtx.globalAlpha = 1;
_drawShape(_particleCtx, p, color);
}
_particleRAF = requestAnimationFrame(_particleLoop);
}
function startParticles() {
if (_particleCanvas) stopParticles();
_particleCanvas = document.createElement('canvas');
_particleCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:999980;';
document.body.appendChild(_particleCanvas);
_particleCtx = _particleCanvas.getContext('2d');
_particles = Array.from({ length: _particleCfg.count }, _makeParticle);
_particles.forEach(p => { p.y = Math.random() * window.innerHeight; });
_particleCfg.active = true;
_particleLoop();
}
function stopParticles() {
_particleCfg.active = false;
if (_particleRAF) { cancelAnimationFrame(_particleRAF); _particleRAF = null; }
if (_particleCanvas) { _particleCanvas.remove(); _particleCanvas = null; _particleCtx = null; }
_particles = [];
}
document.getElementById('cm-particles-toggle').addEventListener('change', function() {
if (this.checked) startParticles(); else stopParticles();
});
const particlesCountSlider = document.getElementById('cm-particles-count');
const particlesCountFill = document.getElementById('cm-particles-count-fill');
particlesCountSlider.addEventListener('input', function() {
_particleCfg.count = parseInt(this.value);
document.getElementById('cm-particles-count-val').textContent = this.value;
updateSliderFill(this, particlesCountFill, 10, 300);
});
const particlesSizeSlider = document.getElementById('cm-particles-size');
const particlesSizeFill = document.getElementById('cm-particles-size-fill');
particlesSizeSlider.addEventListener('input', function() {
_particleCfg.size = parseInt(this.value);
document.getElementById('cm-particles-size-val').textContent = this.value + 'px';
updateSliderFill(this, particlesSizeFill, 1, 20);
});
const particlesSpeedSlider = document.getElementById('cm-particles-speed');
const particlesSpeedFill = document.getElementById('cm-particles-speed-fill');
particlesSpeedSlider.addEventListener('input', function() {
_particleCfg.speed = parseFloat(this.value);
document.getElementById('cm-particles-speed-val').textContent = parseFloat(this.value).toFixed(1) + 'x';
updateSliderFill(this, particlesSpeedFill, 0.2, 5.0);
_particles.forEach(p => { p.vy = (1.0 + Math.random() * 1.5) * _particleCfg.speed; });
});
document.getElementById('cm-particles-color').addEventListener('input', function() { _particleCfg.color = this.value; });
document.getElementById('cm-particles-rainbow').addEventListener('change', function() { _particleCfg.rainbow = this.checked; });
document.getElementById('cm-particles-glow').addEventListener('change', function() { _particleCfg.glow = this.checked; });
document.querySelectorAll('.cm-shape-btn').forEach(b => {
b.addEventListener('click', function() {
_particleCfg.shape = this.dataset.shape;
document.querySelectorAll('.cm-shape-btn').forEach(x => x.classList.toggle('active', x.dataset.shape === _particleCfg.shape));
});
});
// ── OVERLAY IMAGES ─────────────────────────────────────────────────
const OVERLAY_URLS = {
ban: 'https://raw.githubusercontent.com/sevkabevka/sevkabevka.github.io/main/ChatGPT%20Image%2023%20%D0%BC%D0%B0%D1%8F%202026%20%D0%B3.,%2019_13_02.png',
loading: 'https://raw.githubusercontent.com/sevkabevka/sevkabevka.github.io/main/ChatGPT%20Image%2023%20%D0%BC%D0%B0%D1%8F%202026%20%D0%B3.,%2017_59_13_Nero_AI_Image_Upscaler_Photo_Face.png'
};
let _overlayActive = null;
let _overlayImg = { ban: null, loading: null };
let _overlayCanvas = null, _overlayStream = null, _overlayRAF = null;
['ban', 'loading'].forEach(key => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = OVERLAY_URLS[key];
img.onload = () => { _overlayImg[key] = img; };
});
function _pushTrackToAll(stream) {
const track = stream ? stream.getVideoTracks()[0] : null;
if (!track) return;
const scannerVid = document.querySelector('video.scanner-video');
if (scannerVid) scannerVid.srcObject = stream;
if (window._mogPCs) {
for (const pc of window._mogPCs) {
try {
pc.getSenders().forEach(sender => {
if (sender.track?.kind === 'video') sender.replaceTrack(track).catch(() => {});
});
} catch(e) {}
}
}
}
function startOverlay(key) {
if (_overlayRAF) { cancelAnimationFrame(_overlayRAF); _overlayRAF = null; }
if (_overlayStream) { _overlayStream.getTracks().forEach(t => t.stop()); _overlayStream = null; }
_overlayCanvas = null; _overlayActive = null;
const img = _overlayImg[key];
if (!img) { document.getElementById('cm-overlay-status').textContent = 'Loading...'; return; }
_overlayActive = key;
_overlayCanvas = document.createElement('canvas');
_overlayCanvas.width = 640; _overlayCanvas.height = 480;
const ctx = _overlayCanvas.getContext('2d');
function drawOverlay() {
if (!_overlayActive) return;
ctx.save(); ctx.translate(640, 0); ctx.scale(-1, 1);
ctx.drawImage(img, 0, 0, 640, 480);
ctx.restore();
_overlayRAF = requestAnimationFrame(drawOverlay);
}
drawOverlay();
_overlayStream = _overlayCanvas.captureStream(30);
_pushTrackToAll(_overlayStream);
document.getElementById('cm-overlay-status').textContent = key.toUpperCase();
document.getElementById('cm-overlay-status').style.color = key === 'ban' ? 'var(--cm-danger)' : 'var(--cm-accent)';
}
function stopOverlay() {
if (_overlayRAF) { cancelAnimationFrame(_overlayRAF); _overlayRAF = null; }
if (_overlayStream) { _overlayStream.getTracks().forEach(t => t.stop()); _overlayStream = null; }
_overlayActive = null; _overlayCanvas = null;
if (_camSpoofActive && _camStream) {
_pushTrackToAll(_camStream);
} else {
_trueOriginalGetUserMedia({ video: true }).then(realStream => { _pushTrackToAll(realStream); }).catch(() => {});
}
document.getElementById('cm-overlay-status').textContent = 'None';
document.getElementById('cm-overlay-status').style.color = 'var(--cm-text-muted)';
}
document.getElementById('cm-ban-overlay-toggle').addEventListener('change', function() {
document.getElementById('cm-loading-overlay-toggle').checked = false;
if (this.checked) startOverlay('ban'); else stopOverlay();
});
document.getElementById('cm-loading-overlay-toggle').addEventListener('change', function() {
document.getElementById('cm-ban-overlay-toggle').checked = false;
if (this.checked) startOverlay('loading'); else stopOverlay();
});
}
// ── ZUSTAND STATUS BADGE ──────────────────────────���─────────────────────
const _zustandInterval = setInterval(() => {
const badge = document.getElementById('cm-zustand-val');
if (!badge) return;
try {
const wpChunk = _window.webpackChunk_N_E || _window.webpackChunknextjs_app || _window.webpackChunk;
if (!wpChunk) return;
let req;
try { req = wpChunk.push([[Symbol()], {}, e => e]); } catch(e) { return; }
if (typeof req !== 'function') return;
let store = null;
try {
const mod = req(16225);
if (mod) {
store = Object.values(mod).find(v =>
v && typeof v.getState === 'function' && 'selfScore' in (v.getState() || {})
);
}
} catch(e) {}
if (!store && req.m) {
for (const id of Object.keys(req.m)) {
try {
const mod = req(id);
if (!mod || typeof mod !== 'object') continue;
const found = Object.values(mod).find(v =>
v && typeof v.getState === 'function' && 'selfScore' in (v.getState() || {})
);
if (found) { store = found; break; }
} catch(e) {}
}
}
if (store && store.getState().setMyScore?.__patched) {
badge.textContent = 'HOOKED';
badge.style.color = 'var(--cm-success)';
clearInterval(_zustandInterval);
}
} catch(e) {}
}, 500);
function log(...args) {
if (CONFIG.debug) console.log('[cheatmoggle]', ...args);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', buildMenu);
} else {
buildMenu();
}
})();