// ==UserScript==
// @name PokeSurvivor Master Suite (Silph Tactical Edition)
// @namespace https://github.com/DevKenzi/pokesurvivor-suite
// @version 2.9.2
// @description Map ESP Radar, Insta-Chest, Infinite Rerolls, Arceus Aegis & Legal Overdrive for official leaderboards!
// @author DevKenzi
// @match https://pokesurvivor.com/*
// @icon https://pokesurvivor.com/assets/icons/icon-96.png
// @supportURL https://github.com/DevKenzi/pokesurvivor-suite/issues
// @contributionURL https://buymeacoffee.com/xkenzix
// @license GPL-3.0-or-later
// @grant none
// @run-at document-start
// ==/UserScript==
/* global G, GM_info */
/**
* ============================================================================
* [*] PokeSurvivor Master Suite - Silph Tactical Edition (Standalone)
* Version: 2.9.2
*
* Features:
* - Silph Tactical HUD: High-grade gaming overlay with zero AI slop
* - Clean URL Masking: Seamlessly play on pokesurvivor.com without dev.html in address bar
* - Visual ESP Radar: On-screen markers & directional edge arrows for chests, altars, springs & bosses
* - Insta-Chest: Chests open instantly on contact (0.01s instead of 3.5s)
* - Infinite Card Rerolls: Reroll level-up choices indefinitely (Reroll INF) to build your dream kit
* - Arceus Aegis: Complete protection from lethal 30m+ Judgment touch, pillars & cross beams
* - Account Booster: 999,999 coins, tickets, all Pokemon + Shiny variants, max upgrades
* - God-Buff Overdrive: 42,000 HP, 1800x Atk, 25x faster cooldown, Shell Bell lifesteal, 2500 magnet
* - Leaderboard Auto-Compliance: Enforces clean() & Firebase limits (45:00 max, 31.5k kills) for TOP 1
* ============================================================================
*/
(function() {
'use strict';
const SUITE_VERSION = (typeof GM_info !== 'undefined' && GM_info.script && GM_info.script.version) ? GM_info.script.version : '2.9.2';
// =========================================================================
// 1. SEAMLESS REDIRECT & ADDRESS MASKING
// =========================================================================
if (location.pathname === '/' || location.pathname === '/index.html') {
location.replace('/dev.html' + location.search + location.hash);
return;
}
if (location.pathname.includes('dev.html')) {
try {
history.replaceState(null, '', '/' + location.search + location.hash);
} catch (e) {}
}
if (window._psMasterLoaded) return;
window._psMasterLoaded = true;
console.log('%c[Poke-Suite v2.9.2] Initializing Silph Tactical Suite...', 'color:#ef4444;font-weight:bold;font-size:14px;');
// =========================================================================
// 2. USER SETTINGS (LOCALSTORAGE)
// =========================================================================
const SETTINGS_KEY = 'ps_suite_settings';
const defaultSettings = {
esp: true,
espChests: true,
espAltars: true,
espSprings: true,
espBosses: true,
instaChest: true,
infiniteRerolls: true,
arceusShield: true
};
let cfg = Object.assign({}, defaultSettings);
try {
const saved = localStorage.getItem(SETTINGS_KEY);
if (saved) {
const parsed = JSON.parse(saved);
delete parsed.godBuffActive;
delete parsed.godMode;
delete parsed.afkMode;
delete parsed.afkAutoPick;
cfg = Object.assign(cfg, parsed);
}
const cleanStorage = Object.assign({}, cfg);
delete cleanStorage.godBuffActive;
delete cleanStorage.godMode;
delete cleanStorage.afkMode;
delete cleanStorage.afkAutoPick;
localStorage.setItem(SETTINGS_KEY, JSON.stringify(cleanStorage));
} catch (e) {}
// In-memory runtime state only: strictly false on page load / match start
cfg.godBuffActive = false;
function saveCfg() {
try {
const toSave = Object.assign({}, cfg);
delete toSave.godBuffActive;
delete toSave.godMode;
delete toSave.afkMode;
localStorage.setItem(SETTINGS_KEY, JSON.stringify(toSave));
} catch (e) {}
}
// =========================================================================
// 3. UI INITIALIZATION & STYLES
// =========================================================================
function bootSuite() {
if (!document.body) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', bootSuite);
} else {
setTimeout(bootSuite, 50);
}
return;
}
const oldUI = document.getElementById('ps-suite-root');
if (oldUI) oldUI.remove();
const styleEl = document.createElement('style');
styleEl.textContent = `
#ps-suite-root * { box-sizing: border-box; }
.ps-poke-switch { position: relative; width: 38px; height: 20px; display: inline-block; cursor: pointer; }
.ps-poke-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.ps-poke-track {
position: absolute; inset: 0;
background: #0f172a; border-radius: 9999px;
border: 1.5px solid #334155;
transition: all 0.22s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: inset 0 2px 4px rgba(0,0,0,0.6);
}
.ps-poke-switch input:checked + .ps-poke-track {
background: #1e293b; border-color: #ef4444;
box-shadow: 0 0 10px rgba(239, 68, 68, 0.4), inset 0 2px 4px rgba(0,0,0,0.6);
}
.ps-poke-knob {
position: absolute; top: 1.5px; left: 1.5px;
width: 14px; height: 14px; border-radius: 50%;
border: 1px solid #1e293b;
background: linear-gradient(180deg, #ef4444 0%, #ef4444 48%, #1e293b 48%, #1e293b 52%, #ffffff 52%, #ffffff 100%);
transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 3px rgba(0,0,0,0.5);
}
.ps-poke-knob:after {
content: ""; position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 4px; height: 4px; border-radius: 50%;
background: #ffffff; border: 1px solid #0f172a;
}
.ps-poke-switch input:checked + .ps-poke-track .ps-poke-knob {
transform: translateX(18px) rotate(180deg);
box-shadow: 0 0 6px rgba(239, 68, 68, 0.8);
}
.ps-tab-btn {
flex: 1; padding: 7px 0; text-align: center;
font-size: 10px; font-weight: 800; letter-spacing: 0.5px;
color: #94a3b8; background: transparent;
border: none; border-radius: 6px; cursor: pointer;
transition: all 0.15s ease; font-family: inherit;
}
.ps-tab-btn:hover { color: #f8fafc; }
.ps-tab-btn.active {
background: linear-gradient(180deg, #ef4444, #dc2626);
color: #ffffff; box-shadow: 0 2px 8px rgba(220, 38, 38, 0.4);
}
.ps-row {
background: rgba(15, 23, 42, 0.85);
border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 10px; padding: 9px 12px;
display: flex; align-items: center; justify-content: space-between;
transition: all 0.15s ease;
}
.ps-row:hover {
background: rgba(30, 41, 59, 0.7);
border-color: rgba(239, 68, 68, 0.35);
}
.ps-btn-tactical {
border: none; border-radius: 8px; font-weight: 800;
cursor: pointer; transition: all 0.15s ease; outline: none; font-family: inherit;
}
.ps-btn-tactical:hover { filter: brightness(1.15); transform: translateY(-1px); }
.ps-btn-tactical:active { transform: scale(0.98); }
`;
(document.head || document.documentElement).appendChild(styleEl);
const root = document.createElement('div');
root.id = 'ps-suite-root';
root.style = 'position:fixed;top:16px;right:16px;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;user-select:none;pointer-events:auto;';
root.innerHTML = `
SILPH SCOPE
GEN-9
v${SUITE_VERSION}
Rare Candy Overdrive
45k HP - 1,900x ATK - Shell Bell
OFF
Professor's PC
All Pokemon + Shinies + 999k Coins
`;
document.body.appendChild(root);
const floatBtn = document.getElementById('ps-float-btn');
const mainPanel = document.getElementById('ps-main-panel');
function toggleMenu() {
const mp = document.getElementById('ps-main-panel');
if (!mp) return;
mp.style.display = (mp.style.display === 'none' || !mp.style.display) ? 'block' : 'none';
}
if (floatBtn) floatBtn.onclick = toggleMenu;
window.toggleSilphMenu = toggleMenu;
window.addEventListener('keydown', e => {
if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
if (e.code === 'KeyH' || e.key === 'h' || e.key === 'H') {
e.preventDefault();
e.stopImmediatePropagation();
toggleMenu();
}
}, true);
// Tab switcher
const tabBtns = root.querySelectorAll('.ps-tab-btn');
const tabPanes = root.querySelectorAll('.ps-tab-pane');
tabBtns.forEach(btn => {
btn.onclick = () => {
const target = btn.getAttribute('data-tab');
tabBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
tabPanes.forEach(pane => {
pane.style.display = pane.id === 'ps-tab-' + target ? (target === 'radar' ? 'block' : 'flex') : 'none';
});
};
});
const bindCheck = (id, prop) => {
const el = document.getElementById(id);
if (!el) return;
el.onchange = () => { cfg[prop] = el.checked; saveCfg(); };
};
bindCheck('ps-c-esp', 'esp');
bindCheck('ps-c-chests', 'espChests');
bindCheck('ps-c-altars', 'espAltars');
bindCheck('ps-c-springs', 'espSprings');
bindCheck('ps-c-bosses', 'espBosses');
bindCheck('ps-c-chest', 'instaChest');
bindCheck('ps-c-arceus', 'arceusShield');
const rrInput = document.getElementById('ps-c-rr');
if (rrInput) {
rrInput.onchange = () => {
cfg.infiniteRerolls = rrInput.checked;
saveCfg();
syncRerollState();
};
}
// Account Booster
document.getElementById('ps-btn-account').onclick = () => {
const maxU = { hp:10, atk:10, spd:8, cd:8, def:8, regen:5, magnet:6, xp:8, coins:8, moves:1, crit:10, reroll:5, ban:3, start:1 };
if (typeof G !== 'undefined' && G.DB && G.DB.save) {
G.DB.save.coins = 999999;
G.DB.save.tickets = { t1: 99, t10: 99 };
G.DB.save.pupg = G.DB.save.pupg || {};
G.DB.save.owned = G.DB.save.owned || {};
G.DB.save.shiny = G.DB.save.shiny || {};
for (let d = 1; d <= 1025; d++) {
G.DB.save.pupg[d] = { ...maxU };
if (!G.DB.save.owned[d]) G.DB.save.owned[d] = { at: Date.now(), from: 'trainer' };
if (!G.DB.save.shiny[d]) G.DB.save.shiny[d] = { at: Date.now(), from: 'trainer' };
}
if (typeof G.DB.commit === 'function') G.DB.commit();
if (typeof G.DB.saveNow === 'function') G.DB.saveNow();
}
for (let i = 0; i < localStorage.length; i++) {
const k = localStorage.key(i);
if (k && k.startsWith('ps.save.')) {
try {
const s = JSON.parse(localStorage.getItem(k));
if (!s) continue;
s.coins = 999999;
s.tickets = { t1: 99, t10: 99 };
s.pupg = s.pupg || {};
s.owned = s.owned || {};
s.shiny = s.shiny || {};
for (let d = 1; d <= 1025; d++) {
s.pupg[d] = { ...maxU };
s.owned[d] = { at: Date.now(), from: 'trainer' };
s.shiny[d] = { at: Date.now(), from: 'trainer' };
}
localStorage.setItem(k, JSON.stringify(s));
} catch (e) {}
}
}
alert('[OK] SUCCESS! Max upgrades applied, 999,999 coins & tickets added, all Pokemon + Shiny forms unlocked!');
};
// God-Buff Toggle System
function updateGodBtn() {
const btn = document.getElementById('ps-btn-god');
const badge = document.getElementById('ps-god-badge');
if (!btn || !badge) return;
if (cfg.godBuffActive) {
btn.style.background = 'linear-gradient(135deg, #dc2626, #b91c1c)';
btn.style.color = '#ffffff';
btn.style.borderColor = '#ef4444';
btn.textContent = 'Deactivate Overdrive';
badge.textContent = 'ACTIVE';
badge.style.background = '#ef4444';
badge.style.color = '#ffffff';
} else {
btn.style.background = '#1e293b';
btn.style.color = '#f1f5f9';
btn.style.borderColor = 'rgba(239, 68, 68, 0.4)';
btn.textContent = 'Activate Overdrive';
badge.textContent = 'OFF';
badge.style.background = '#1e293b';
badge.style.color = '#94a3b8';
}
}
function toggleGodBuff() {
const pl = (typeof G !== 'undefined' && G.Game && G.Game.player) || (typeof G !== 'undefined' && G.Combat && G.Combat.player);
if (!pl) {
alert('[!] Please start or enter a match first to toggle God-Tier stats!');
return;
}
cfg.godBuffActive = !cfg.godBuffActive;
if (cfg.godBuffActive) {
if (!pl._psOrigStats) {
pl._psOrigStats = {
maxHp: pl.maxHp || 100,
hp: pl.hp || 100,
atkMul: pl.atkMul || 1,
cdMul: pl.cdMul || 1,
spdMul: pl.spdMul || 1,
magnet: pl.magnet || 100
};
}
pl.maxHp = 42000;
pl.hp = 42000;
pl.atkMul = 1800;
pl.cdMul = 0.04;
pl.spdMul = 3.2;
pl.magnet = 2500;
if (typeof pl.equip === 'function') pl.equip('shellbell');
} else {
if (pl._psOrigStats) {
pl.maxHp = pl._psOrigStats.maxHp;
pl.hp = Math.min(pl.hp, pl._psOrigStats.maxHp);
pl.atkMul = pl._psOrigStats.atkMul;
pl.cdMul = pl._psOrigStats.cdMul;
pl.spdMul = pl._psOrigStats.spdMul;
pl.magnet = pl._psOrigStats.magnet;
}
}
updateGodBtn();
}
const godBtn = document.getElementById('ps-btn-god');
if (godBtn) godBtn.onclick = toggleGodBuff;
updateGodBtn();
setInterval(() => {
const pl = (typeof G !== 'undefined' && G.Game && G.Game.player);
if (!pl || pl.dead) {
if (cfg.godBuffActive) {
cfg.godBuffActive = false;
updateGodBtn();
}
return;
}
if (cfg.godBuffActive) {
// Enforce clean() boundaries so upgrades never fail anti-cheat
if (pl.maxHp > 48000) pl.maxHp = 48000;
if (pl.hp > pl.maxHp) pl.hp = pl.maxHp;
if (pl.atkMul > 1950) pl.atkMul = 1950;
if (pl.cdMul < 0.035) pl.cdMul = 0.035;
if (pl.spdMul > 22) pl.spdMul = 22;
if (pl.hp < pl.maxHp) pl.hp = pl.maxHp;
}
if (pl._psLegitBonus === undefined) {
pl._psLegitBonus = (pl.rerollBonus !== 9999) ? (pl.rerollBonus || 0) : 0;
pl._psLegitRerolls = (pl.rerollBonus !== 9999) ? (pl.rerolls || 0) : 0;
}
if (cfg.infiniteRerolls) {
pl.rerollBonus = 9999;
pl.rerolls = 0;
}
}, 200);
setupESP();
}
// =========================================================================
// 4. SZYBKIE SKRZYNKI (INSTA-CHEST)
// =========================================================================
function hookInteract() {
if (typeof G !== 'undefined' && G.Interact && G.Interact.update) {
if (G.Interact._psHooked) return;
G.Interact._psHooked = true;
const origInteract = G.Interact.update;
G.Interact.update = function(dt, pl) {
if (cfg.instaChest && pl && G.World && G.World.specialsNear) {
const near = G.World.specialsNear(pl.x, pl.y, 90);
near.forEach(p => { if (p.type === 'bigchest' && !p.used) p.open = 3.5; });
}
return origInteract.apply(this, arguments);
};
} else {
setTimeout(hookInteract, 500);
}
}
hookInteract();
// =========================================================================
// 5. ARCEUS AEGIS (NEUTRALIZE JUDGMENT PILLARS, BEAMS & TOUCH FOR TOP 1)
// =========================================================================
function hookArceusAegis() {
// 1. Hook G.Player.prototype.hurt (Clean: Object.prototype.hasOwnProperty is FALSE)
if (typeof G !== 'undefined' && G.Player && G.Player.prototype && !G.Player._psHurtHooked) {
G.Player._psHurtHooked = true;
const origHurt = G.Player.prototype.hurt;
G.Player.prototype.hurt = function(amount, type, pure, cat) {
if (cfg.arceusShield) {
const inJudgment = (typeof G !== 'undefined' && G.Judgment && G.Judgment.active);
if (pure || inJudgment || (this.maxHp && amount >= this.maxHp * 0.15)) {
// Complete nullification: Arceus touch, Judgment hazards & multiplying legendaries
return;
}
}
return origHurt.apply(this, arguments);
};
}
// 2. Hook G.Hazards (Arceus drops 30%-40% maxHp pillars and beams)
if (typeof G !== 'undefined' && G.Hazards && !G.Hazards._psHooked) {
G.Hazards._psHooked = true;
const origAdd = G.Hazards.add;
if (typeof origAdd === 'function') {
G.Hazards.add = function(h, fromNet) {
if (cfg.arceusShield && h && (h.pct || h.vis === 'pillar' || h.color === '#ffd25e' || h.color === '#fff3b0')) {
h.pct = 0;
h.dmg = 0;
}
return origAdd.apply(this, arguments);
};
}
}
// 3. Hook G.Judgment.update
if (typeof G !== 'undefined' && G.Judgment && G.Judgment.update && !G.Judgment._psHooked) {
G.Judgment._psHooked = true;
const origJudgUpdate = G.Judgment.update;
G.Judgment.update = function(dt, pl, time) {
if (cfg.arceusShield && pl) {
const plProxy = new Proxy(pl, {
get(target, prop, receiver) {
if (prop === 'hurt') return () => 0;
const val = Reflect.get(target, prop, receiver);
return typeof val === 'function' ? val.bind(target) : val;
}
});
return origJudgUpdate.call(this, dt, plProxy, time);
}
return origJudgUpdate.apply(this, arguments);
};
}
if (!window.G || !window.G.Player || !window.G.Player._psHurtHooked || !window.G.Hazards || !window.G.Hazards._psHooked) {
setTimeout(hookArceusAegis, 300);
}
}
hookArceusAegis();
// =========================================================================
// 6. INFINITE REROLLS (REROLL INF) & RESTORING LEGIT STATE
// =========================================================================
function syncRerollState() {
const pl = (typeof G !== 'undefined' && G.Game && G.Game.player);
if (!pl) return;
if (pl._psLegitBonus === undefined) {
pl._psLegitBonus = (pl.rerollBonus !== 9999) ? (pl.rerollBonus || 0) : 0;
pl._psLegitRerolls = (pl.rerollBonus !== 9999) ? (pl.rerolls || 0) : 0;
}
const btn = document.getElementById('lvl-reroll');
const num = document.getElementById('lvl-rr-n');
if (cfg.infiniteRerolls) {
pl.rerollBonus = 9999;
pl.rerolls = 0;
if (btn) btn.classList.remove('hidden');
if (num) num.textContent = '\u221E';
} else {
// Revert from 9999 back to legitimate user stats
pl.rerollBonus = pl._psLegitBonus !== undefined ? pl._psLegitBonus : 0;
pl.rerolls = pl._psLegitRerolls !== undefined ? pl._psLegitRerolls : 0;
const left = Math.max(0, 1 + (pl.rerollBonus || 0) - (pl.rerolls || 0));
if (num) num.textContent = left;
if (btn) btn.classList.toggle('hidden', left <= 0);
}
}
function hookRunUI() {
if (typeof G !== 'undefined' && G.RunUI && G.RunUI.showLevelUp) {
if (G.RunUI._psHooked) return;
G.RunUI._psHooked = true;
const origShowLevelUp = G.RunUI.showLevelUp;
G.RunUI.showLevelUp = function() {
const pl = (typeof G !== 'undefined' && G.Game && G.Game.player);
if (pl && pl._psLegitBonus === undefined) {
pl._psLegitBonus = (pl.rerollBonus !== 9999) ? (pl.rerollBonus || 0) : 0;
pl._psLegitRerolls = (pl.rerollBonus !== 9999) ? (pl.rerolls || 0) : 0;
}
if (pl && cfg.infiniteRerolls) {
pl.rerollBonus = 9999;
pl.rerolls = 0;
}
const res = origShowLevelUp.apply(this, arguments);
setTimeout(syncRerollState, 0);
return res;
};
} else {
setTimeout(hookRunUI, 500);
}
}
hookRunUI();
document.addEventListener('click', e => {
if (e.target && (e.target.id === 'lvl-reroll' || e.target.closest('#lvl-reroll'))) {
const pl = typeof G !== 'undefined' && G.Game && G.Game.player;
if (!pl) return;
if (cfg.infiniteRerolls) {
pl.rerollBonus = 9999;
pl.rerolls = 0;
setTimeout(syncRerollState, 35);
} else {
setTimeout(() => {
if (pl && pl._psLegitBonus !== undefined) {
pl._psLegitRerolls = pl.rerolls || 0;
}
syncRerollState();
}, 35);
}
}
}, true);
// =========================================================================
// 6. OFFICIAL LEADERBOARD COMPLIANCE FILTER (FIREBASE RULES GUARANTEE)
// =========================================================================
function hookRankingFilter() {
if (typeof G !== 'undefined' && G.Ranking && G.Ranking.submitSolo) {
if (G.Ranking._psFiltered) return;
G.Ranking._psFiltered = true;
const origSubmit = G.Ranking.submitSolo;
G.Ranking.submitSolo = function(r) {
if (r && typeof r === 'object') {
// 1. Cap time to 45:00 (2700s) maximum allowed by Firebase rule (d.t <= 2700)
if (r.t > 2700) r.t = 2700;
// 2. Cap kills to safe limit under Firebase formula: d.kills <= 100 + d.t * 12 (max 32,500 at 45m)
const maxKills = Math.floor(100 + (r.t || 2700) * 11.5);
if (r.kills > maxKills) r.kills = maxKills;
// 3. Cap level under Firebase formula: d.lv <= 10 + d.t / 4
const maxLv = Math.floor(10 + (r.t || 2700) / 4);
if (r.lv > maxLv) r.lv = maxLv;
}
const p = origSubmit.apply(this, arguments);
if (p && typeof p.then === 'function') {
p.then(() => {
// Flush ranking caches so local browser refreshes instantly
for (let i = localStorage.length - 1; i >= 0; i--) {
const k = localStorage.key(i);
if (k && (k.startsWith('ps.rk.c.') || k.startsWith('ps.rk.b.'))) {
localStorage.removeItem(k);
}
}
}).catch(() => {});
}
return p;
};
} else {
setTimeout(hookRankingFilter, 400);
}
}
hookRankingFilter();
// =========================================================================
// 7. VISUAL ESP RADAR (TACTICAL CANVAS OVERLAY)
// =========================================================================
function setupESP() {
const gameCv = document.getElementById('game');
if (!gameCv) {
setTimeout(setupESP, 250);
return;
}
if (document.getElementById('ps-esp-layer')) return;
const espCv = document.createElement('canvas');
espCv.id = 'ps-esp-layer';
espCv.style = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:9999;';
document.body.appendChild(espCv);
const ctx = espCv.getContext('2d');
let currentDpr = 1;
function resize() {
const rect = gameCv.getBoundingClientRect();
currentDpr = window.devicePixelRatio || 1;
espCv.style.left = rect.left + 'px';
espCv.style.top = rect.top + 'px';
espCv.style.width = rect.width + 'px';
espCv.style.height = rect.height + 'px';
espCv.width = Math.round(rect.width * currentDpr);
espCv.height = Math.round(rect.height * currentDpr);
}
window.addEventListener('resize', resize);
resize();
let pulse = 0;
function renderESP() {
requestAnimationFrame(renderESP);
if (!cfg.esp) {
ctx.clearRect(0, 0, espCv.width, espCv.height);
return;
}
if (typeof G === 'undefined' || !G.Game || !G.Game.player || !G.Camera) {
ctx.clearRect(0, 0, espCv.width, espCv.height);
return;
}
const rect = gameCv.getBoundingClientRect();
const dpr = window.devicePixelRatio || 1;
const targetW = Math.round(rect.width * dpr);
const targetH = Math.round(rect.height * dpr);
if (espCv.width !== targetW || espCv.height !== targetH) {
resize();
}
ctx.save();
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.clearRect(0, 0, rect.width, rect.height);
pulse += 0.05;
const pl = G.Game.player, cam = G.Camera;
const W = rect.width, H = rect.height;
// Exact pixel-perfect world-to-screen coordinate mapping
const scale = cam.scale;
const camLeft = cam.left() - (cam._sx || 0);
const camTop = cam.top() - (cam._sy || 0);
const toScreenX = wx => (wx - camLeft) * scale;
const toScreenY = wy => (wy - camTop) * scale;
const px = toScreenX(pl.x);
const py = toScreenY(pl.y);
// Collect targets
const targets = [];
// 1. Interactive map specials (chests, altars, healing springs)
if (G.World && typeof G.World.specialsNear === 'function') {
const specials = G.World.specialsNear(pl.x, pl.y, 4500) || [];
const springs = [];
for (const s of specials) {
if (!s) continue;
if (s.type === 'bigchest' && cfg.espChests && !s.used && s.open < 3.5) {
targets.push({
x: s.x,
y: s.y,
yOffset: -12,
r: 22,
icon: '\u{1F381}',
name: 'CHEST',
color: '#fbbf24',
borderColor: '#fbbf24',
isBoss: false
});
} else if (s.type === 'altar' && cfg.espAltars && !s.used) {
targets.push({
x: s.x,
y: s.y,
yOffset: -14,
r: 20,
icon: '\u26A1',
name: 'ALTAR',
color: '#38bdf8',
borderColor: '#38bdf8',
isBoss: false
});
} else if (s.type === 'spring' && cfg.espSprings && s.charge >= 0.1) {
springs.push(s);
}
}
// Limit springs: show on-screen springs, but for off-screen springs only show the closest 2 to prevent edge clutter
if (springs.length > 0) {
springs.sort((a, b) => Math.hypot(a.x - pl.x, a.y - pl.y) - Math.hypot(b.x - pl.x, b.y - pl.y));
let offScreenSpringCount = 0;
for (const s of springs) {
const sx = toScreenX(s.x);
const sy = toScreenY(s.y);
const isOn = (sx >= 44 && sx <= W - 44 && sy >= 44 && sy <= H - 44);
if (isOn || offScreenSpringCount < 2) {
if (!isOn) offScreenSpringCount++;
targets.push({
x: s.x,
y: s.y,
yOffset: -6,
r: 26,
icon: '\u{1F4A7}',
name: 'HEAL',
color: '#4ade80',
borderColor: '#4ade80',
isBoss: false
});
}
}
}
}
// 2. Bosses and Rare Spawns (from G.EnemyMgr)
if (cfg.espBosses && G.EnemyMgr && typeof G.EnemyMgr.all === 'function') {
const enemies = G.EnemyMgr.all() || [];
for (const e of enemies) {
if (!e || e.dead || e.hp <= 0) continue;
if (e.boss) {
const bName = e.name ? e.name.toUpperCase() : 'BOSS';
const hpPct = e.maxHp > 0 ? Math.round((e.hp / e.maxHp) * 100) : 100;
targets.push({
x: e.x,
y: e.y,
yOffset: -(e.bodyH ? e.bodyH * 0.45 : 18),
r: Math.max(26, (e.r || 20) * 1.25),
icon: '\u{1F451}',
name: `${bName} [${hpPct}%]`,
color: '#ef4444',
borderColor: '#ef4444',
isBoss: true
});
} else if (e.shiny) {
const sName = e.name ? e.name.toUpperCase() : 'SHINY';
targets.push({
x: e.x,
y: e.y,
yOffset: -(e.bodyH ? e.bodyH * 0.45 : 14),
r: 22,
icon: '\u2728',
name: `SHINY ${sName}`,
color: '#f472b6',
borderColor: '#f472b6',
isBoss: false
});
}
}
}
// Render radar markers and edge arrows
const pad = 44;
const edgeItems = [];
for (const t of targets) {
const ox = toScreenX(t.x);
const oy = toScreenY(t.y + (t.yOffset || 0));
const dx = ox - px;
const dy = oy - py;
const dist = Math.round(Math.hypot(t.x - pl.x, t.y - pl.y) / 20);
const onScreen = (ox >= pad && ox <= W - pad && oy >= pad && oy <= H - pad);
if (onScreen) {
const r = t.r + Math.sin(pulse) * 3;
ctx.save();
ctx.strokeStyle = t.borderColor;
ctx.lineWidth = t.isBoss ? 3 : 2;
ctx.beginPath();
ctx.arc(ox, oy, r, 0, Math.PI * 2);
ctx.stroke();
if (t.isBoss) {
// Tactical crosshair corners for bosses
ctx.lineWidth = 1.5;
const cL = 8;
ctx.beginPath();
ctx.moveTo(ox - r - 4, oy - r + cL); ctx.lineTo(ox - r - 4, oy - r - 4); ctx.lineTo(ox - r + cL, oy - r - 4);
ctx.moveTo(ox + r + 4, oy - r + cL); ctx.lineTo(ox + r + 4, oy - r - 4); ctx.lineTo(ox + r - cL, oy - r - 4);
ctx.moveTo(ox - r - 4, oy + r - cL); ctx.lineTo(ox - r - 4, oy + r + 4); ctx.lineTo(ox - r + cL, oy + r + 4);
ctx.moveTo(ox + r + 4, oy + r - cL); ctx.lineTo(ox + r + 4, oy + r + 4); ctx.lineTo(ox + r - cL, oy + r + 4);
ctx.stroke();
}
// Tactical Badge Tag
const label = `${t.icon} ${t.name} [${dist}m]`;
ctx.font = 'bold 10px "Segoe UI Emoji", "Apple Color Emoji", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
const tm = ctx.measureText(label);
const bgW = tm.width + 14;
const bgH = 18;
const bgX = ox - bgW / 2;
const bgY = oy - r - 22;
ctx.fillStyle = 'rgba(7, 10, 18, 0.88)';
ctx.fillRect(bgX, bgY, bgW, bgH);
ctx.strokeStyle = t.borderColor;
ctx.lineWidth = 1;
ctx.strokeRect(bgX, bgY, bgW, bgH);
ctx.fillStyle = t.color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(label, ox, bgY + bgH / 2);
ctx.restore();
} else {
// Directional Edge Indicator
const ang = Math.atan2(dy, dx);
const minX = pad, maxX = W - pad;
const minY = pad, maxY = H - pad;
let tRay = Infinity;
if (dx > 0) tRay = Math.min(tRay, (maxX - px) / dx);
if (dx < 0) tRay = Math.min(tRay, (minX - px) / dx);
if (dy > 0) tRay = Math.min(tRay, (maxY - py) / dy);
if (dy < 0) tRay = Math.min(tRay, (minY - py) / dy);
if (!isFinite(tRay) || tRay < 0) tRay = 0;
const edgeX = px + dx * tRay;
const edgeY = py + dy * tRay;
edgeItems.push({ t, edgeX, edgeY, ang, dist });
}
}
// Resolve edge overlaps so badges never collide or stack on top of each other
if (edgeItems.length > 0) {
const minX = pad, maxX = W - pad;
const minY = pad, maxY = H - pad;
const left = [], right = [], top = [], bottom = [];
edgeItems.forEach(it => {
if (Math.abs(it.edgeX - minX) < 4) left.push(it);
else if (Math.abs(it.edgeX - maxX) < 4) right.push(it);
else if (Math.abs(it.edgeY - minY) < 4) top.push(it);
else bottom.push(it);
});
const adjust1D = (arr, coordKey, minVal, maxVal, spacing) => {
arr.sort((a, b) => a[coordKey] - b[coordKey]);
for (let i = 1; i < arr.length; i++) {
if (arr[i][coordKey] < arr[i - 1][coordKey] + spacing) {
arr[i][coordKey] = arr[i - 1][coordKey] + spacing;
}
}
if (arr.length > 0 && arr[arr.length - 1][coordKey] > maxVal) {
let over = arr[arr.length - 1][coordKey] - maxVal;
for (let i = arr.length - 1; i >= 0; i--) {
arr[i][coordKey] -= over;
if (i > 0 && arr[i][coordKey] < arr[i - 1][coordKey] + spacing) {
arr[i - 1][coordKey] = arr[i][coordKey] - spacing;
}
}
}
};
adjust1D(left, 'edgeY', minY, maxY, 34);
adjust1D(right, 'edgeY', minY, maxY, 34);
adjust1D(top, 'edgeX', minX, maxX, 75);
adjust1D(bottom, 'edgeX', minX, maxX, 75);
for (const it of edgeItems) {
const t = it.t;
ctx.save();
ctx.translate(it.edgeX, it.edgeY);
// Arrow
ctx.save();
ctx.rotate(it.ang);
ctx.fillStyle = t.color;
ctx.beginPath();
ctx.moveTo(14, 0);
ctx.lineTo(-7, -7);
ctx.lineTo(-3, 0);
ctx.lineTo(-7, 7);
ctx.closePath();
ctx.fill();
ctx.restore();
// Distance Tag with Icon & Name
const tag = `${t.icon} ${t.name} ${it.dist}m`;
ctx.font = 'bold 10px "Segoe UI Emoji", "Apple Color Emoji", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
const tm = ctx.measureText(tag);
const bw = tm.width + 12;
const bh = 17;
const bx = -bw / 2;
const by = it.edgeY > H - 55 ? -28 : 12;
ctx.fillStyle = 'rgba(7, 10, 18, 0.92)';
ctx.fillRect(bx, by, bw, bh);
ctx.strokeStyle = t.borderColor;
ctx.lineWidth = 1;
ctx.strokeRect(bx, by, bw, bh);
ctx.fillStyle = '#f8fafc';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(tag, 0, by + bh / 2);
ctx.restore();
}
}
ctx.restore();
}
renderESP();
}
bootSuite();
console.log('%c[Poke-Suite v2.9.2] Ready to play with Silph Tactical HUD!', 'color:#ef4444;font-weight:bold;font-size:14px;');
})();