// ==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 [H]
SAFE: RANKING
SILPH SCOPE GEN-9
v${SUITE_VERSION}
Silph Scope Radar
Scan on-screen & edge targets
Key H
[Coffee] Tip Creator
`; 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;'); })();