Killaura, Bot, Dodge, ESP, Zoom, Auto-Respawn and more. Buy me a coffee :) paypal.me/Izkuh Support : Patreon.com/EvoWareV1
// ==UserScript==
// @name EvoWare
// @namespace http://tampermonkey.net/
// @version 1.6
// @description Killaura, Bot, Dodge, ESP, Zoom, Auto-Respawn and more. Buy me a coffee :) paypal.me/Izkuh Support : Patreon.com/EvoWareV1
// @author #Ex
// @match https://evowars.io/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=evowars.io
// @grant none
// @license GPL-3.0
// ==/UserScript==
(function () {
'use strict';
const iframe = document.createElement('iframe');
iframe.id = 'evoware-frame';
iframe.style.cssText = `position:fixed!important;top:50px!important;left:50px!important;width:600px!important;height:690px!important;border:none!important;z-index:2147483647!important;background:transparent!important;pointer-events:auto!important;transition:opacity 0.15s!important;`;
document.body.appendChild(iframe);
const doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(`<!DOCTYPE html><html><head><style>
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%;width:100%}
body{background:rgba(8,4,16,0.96);font-family:'Segoe UI',Arial,sans-serif;color:#b8a0d0;border-radius:12px;border:1px solid #4a2080;box-shadow:0 0 40px rgba(100,20,200,0.4);display:flex;flex-direction:column}
#drag-bar{height:42px;padding:0 16px;font-size:14px;font-weight:600;color:#c8b0f0;border-bottom:1px solid #4a2080;cursor:grab;display:flex;align-items:center;justify-content:space-between;user-select:none;background:linear-gradient(180deg,rgba(30,10,50,0.98),rgba(20,5,35,0.98));flex-shrink:0;border-radius:12px 12px 0 0}
#drag-bar:active{cursor:grabbing}
.body{display:flex;flex:1;background:rgba(12,6,22,0.96);overflow:hidden;border-radius:0 0 12px 12px}
.content{display:flex;padding:14px;gap:14px;overflow-y:auto;flex:1}
.col{flex:1;display:flex;flex-direction:column;gap:10px;min-width:0}
.st{font-size:11px;font-weight:700;letter-spacing:1.5px;margin-bottom:4px;text-transform:uppercase;color:#7050b0}
.sec{background:rgba(18,10,30,0.9);border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:10px;border:1px solid #302050}
.row{display:flex;justify-content:space-between;align-items:center;font-size:13px;color:#c8b8e0;user-select:none;gap:12px}
.tgl{position:relative;width:56px;height:28px;display:inline-block;cursor:pointer;flex-shrink:0}
.tgl input{opacity:0;width:0;height:0;position:absolute}
.sld{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:#2a1840;transition:0.2s;border-radius:28px}
.sld:before{position:absolute;content:"";height:22px;width:22px;left:3px;bottom:3px;background:#6040a0;transition:0.2s;border-radius:50%}
input:checked+.sld{background:#7c3aed;box-shadow:0 0 8px rgba(124,58,237,0.5)}
input:checked+.sld:before{transform:translateX(28px);background:#fff}
.rw{display:flex;align-items:center;gap:8px;flex:1;position:relative}
.slider-wrap{position:relative;width:100%;height:22px}
.slider-wrap input[type=range]{position:absolute;width:100%;top:50%;transform:translateY(-50%);-webkit-appearance:none;appearance:none;background:transparent;pointer-events:none;z-index:2;height:6px}
.slider-wrap input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:#7c3aed;cursor:pointer;pointer-events:auto;border:1px solid #a78bfa;box-shadow:0 0 6px rgba(124,58,237,0.4)}
.slider-track-bg{position:absolute;top:50%;transform:translateY(-50%);width:100%;height:4px;background:#2a1840;border-radius:3px;z-index:1}
.slider-track-fill{position:absolute;top:50%;transform:translateY(-50%);height:4px;background:#7c3aed;border-radius:3px;z-index:1;box-shadow:0 0 6px rgba(124,58,237,0.3)}
.val{color:#8060c0;font-size:11px;min-width:32px;text-align:right;flex-shrink:0}
.stat-val{font-weight:600;font-size:12px}
.help{display:inline-block;width:16px;height:16px;border-radius:50%;background:#4a2080;color:#c8b0f0;text-align:center;line-height:16px;font-size:11px;font-weight:700;cursor:help;margin-left:4px;position:relative}
.help:hover::after{content:attr(data-tip);position:absolute;left:22px;top:-6px;background:#1a0a2e;color:#fff;padding:6px 10px;border-radius:6px;font-size:11px;white-space:nowrap;z-index:10;border:1px solid #7c3aed;max-width:200px;white-space:normal}
select{background:#2a1840;color:#c8b8e0;border:1px solid #4a2080;border-radius:4px;padding:3px 6px;font-size:11px;outline:none}
select option{background:#1a0a2e}
::-webkit-scrollbar{width:4px}
::-webkit-scrollbar-track{background:#1a0a2e}
::-webkit-scrollbar-thumb{background:#4a2080;border-radius:4px}
.hotkey-row{background:rgba(124,58,237,0.15);border:1px solid #7c3aed;border-radius:6px;padding:8px 12px;margin-top:4px}
.hotkey-btn{background:#2a1840;border:1px solid #7c3aed;color:#c8b8e0;padding:4px 12px;border-radius:4px;cursor:pointer;font-size:12px;font-weight:600}
.hotkey-btn:hover{background:#7c3aed;color:#fff}
.hotkey-display{background:#1a0a2e;border:1px solid #4a2080;border-radius:4px;padding:4px 12px;font-family:monospace;font-size:12px;min-width:80px;text-align:center}
.waiting-txt{color:#22c55e;font-size:11px}
</style></head><body>
<div id="drag-bar"><span>⚔ EvoWare</span><span style="font-size:10px;color:#6040a0;font-weight:400">INSERT/hotkey toggle · Drag to move</span></div>
<div class="body"><div class="content">
<div class="col">
<div><div class="st">Combat</div><div class="sec">
<div class="row"><span>Bot<span class="help" data-tip="Auto-moves, hunts enemies, collects food [F key]">?</span></span><label class="tgl"><input type="checkbox" id="tgl-bot"><span class="sld"></span></label></div>
<div class="row"><span>Killaura<span class="help" data-tip="Auto-aim & attack nearest enemy in range">?</span></span><label class="tgl"><input type="checkbox" id="tgl-killaura"><span class="sld"></span></label></div>
<div class="row"><span>Target Level</span><span class="val" id="val-lvlrange">0-100</span></div>
<div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-lvl"></div><input type="range" id="rng-lvlmin" min="0" max="100" value="0" step="1"><input type="range" id="rng-lvlmax" min="0" max="100" value="100" step="1"></div>
<div class="row"><span>Dodge<span class="help" data-tip="Pushes you away from incoming attacks">?</span></span><label class="tgl"><input type="checkbox" id="tgl-dodgeatk"><span class="sld"></span></label></div>
<div class="row"><span>Dodge on CD<span class="help" data-tip="Only dodge when your attack is on cooldown">?</span></span><label class="tgl"><input type="checkbox" id="tgl-dodgecd"><span class="sld"></span></label></div>
<div class="row"><span>Auto Respawn<span class="help" data-tip="Auto-clicks Play after death">?</span></span><label class="tgl"><input type="checkbox" id="tgl-autorespawn"><span class="sld"></span></label></div>
<div class="row"><span>Swing Angle<span class="help" data-tip="Aim offset applied to attack direction">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-offset"></div><input type="range" id="rng-offset" min="0" max="360" value="135"></div><span class="val" id="val-offset">135°</span></div></div>
</div></div>
<div><div class="st">Bot Config</div><div class="sec">
<div class="row"><span>Max Higher Lvl<span class="help" data-tip="Attack enemies up to N levels above you (Max=any)">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-maxhigher"></div><input type="range" id="rng-maxhigher" min="0" max="20" value="0" step="1"></div><span class="val" id="val-maxhigher">0</span></div></div>
<div class="row"><span>Min Lower Lvl<span class="help" data-tip="Ignore enemies more than N levels below you (All=any)">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-minlower"></div><input type="range" id="rng-minlower" min="0" max="20" value="0" step="1"></div><span class="val" id="val-minlower">0</span></div></div>
<div class="row"><span>Safe Distance<span class="help" data-tip="How far to keep from dangerous enemies (multiplier)">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-safedist"></div><input type="range" id="rng-safedist" min="1" max="3" step="0.1" value="2"></div><span class="val" id="val-safedist">2.0x</span></div></div>
<div class="row"><span>Avoid Strength<span class="help" data-tip="How hard to turn away from threats">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-avoidstr"></div><input type="range" id="rng-avoidstr" min="0" max="100" step="1" value="50"></div><span class="val" id="val-avoidstr">50%</span></div></div>
<div class="row"><span>Sprint<span class="help" data-tip="When to right-click for speed boost">?</span></span><select id="sel-sprintmode"><option value="0">Always</option><option value="1" selected>Towards Enemy</option><option value="2">Never</option></select></div>
<div class="row"><span>Collect Food<span class="help" data-tip="Move towards food when no enemy nearby">?</span></span><label class="tgl"><input type="checkbox" id="tgl-collectfood" checked><span class="sld"></span></label></div>
<div class="row"><span>Flee Danger<span class="help" data-tip="Run from enemies too strong to fight">?</span></span><label class="tgl"><input type="checkbox" id="tgl-fleedanger"><span class="sld"></span></label></div>
<div class="row"><span>Skip Teammates<span class="help" data-tip="In Team mode, do not attack same-color allies">?</span></span><label class="tgl"><input type="checkbox" id="tgl-skipteam" checked><span class="sld"></span></label></div>
</div></div>
</div>
<div class="col">
<div><div class="st">Visuals</div><div class="sec">
<div class="row"><span>Enemy Range<span class="help" data-tip="Show enemy attack radius circle">?</span></span><label class="tgl"><input type="checkbox" id="tgl-enemyrange"><span class="sld"></span></label></div>
<div class="row"><span>Attack Timer<span class="help" data-tip="Show enemy attack cooldown ring">?</span></span><label class="tgl"><input type="checkbox" id="tgl-cooldown"><span class="sld"></span></label></div>
<div class="row"><span>Tracers<span class="help" data-tip="Draw lines to each enemy">?</span></span><label class="tgl"><input type="checkbox" id="tgl-tracers"><span class="sld"></span></label></div>
<div class="row"><span>Hitboxes<span class="help" data-tip="Show enemy collision circles">?</span></span><label class="tgl"><input type="checkbox" id="tgl-hitboxes"><span class="sld"></span></label></div>
<div class="row"><span>Target Glow<span class="help" data-tip="Glow highlight on current target">?</span></span><label class="tgl"><input type="checkbox" id="tgl-killable"><span class="sld"></span></label></div>
</div></div>
<div><div class="st">Settings</div><div class="sec">
<div class="row"><span>Zoom<span class="help" data-tip="Camera zoom level">?</span></span><div class="rw"><div class="slider-wrap"><div class="slider-track-bg"></div><div class="slider-track-fill" id="track-zoom"></div><input type="range" id="rng-zoom" min="0.2" max="3" step="0.05" value="0.5"></div><span class="val" id="val-zoom">0.50x</span></div></div>
</div></div>
<div><div class="st">Hotkey</div><div class="sec">
<div class="hotkey-row">
<div class="row"><span>Menu Toggle</span><button class="hotkey-btn" id="change-hotkey">Set</button></div>
<div class="row" style="margin-top:8px"><span>Current:</span><span class="hotkey-display" id="current-hotkey">Insert</span></div>
<div class="row" style="margin-top:4px"><span class="waiting-txt" id="waiting-status"></span></div>
</div>
</div></div>
<div><div class="st">Info</div><div class="sec">
<div class="row"><span>Level</span><span class="stat-val" style="color:#a78bfa" id="txt-level">--</span></div>
<div class="row"><span>Range</span><span class="stat-val" style="color:#c084fc" id="txt-range">--</span></div>
<div class="row"><span>Target</span><span class="stat-val" style="color:#e879f9" id="txt-target">--</span></div>
<div class="row"><span>Nearby</span><span class="stat-val" style="color:#a78bfa" id="txt-nearby">0</span></div>
<div class="row"><span>Bot</span><span class="stat-val" style="color:#4ade80" id="txt-botstate">OFF</span></div>
</div></div>
</div>
</div></div>
<script>
function S(t,d){window.parent.postMessage({evoware:1,type:t,data:d},'*')}
const D=document.getElementById('drag-bar');let dr=false,sx,sy,sl,st2;
D.addEventListener('mousedown',function(e){if(['INPUT','LABEL','SELECT','BUTTON'].includes(e.target.tagName))return;dr=true;sx=e.clientX;sy=e.clientY;const f=window.parent.document.getElementById('evoware-frame');sl=f.offsetLeft;st2=f.offsetTop;e.preventDefault()});
window.addEventListener('mousemove',function(e){if(!dr)return;const f=window.parent.document.getElementById('evoware-frame');let nx=sl+(e.clientX-sx),ny=st2+(e.clientY-sy);nx=Math.max(0,Math.min(nx,window.parent.innerWidth-f.offsetWidth));ny=Math.max(0,Math.min(ny,window.parent.innerHeight-f.offsetHeight));f.style.left=nx+'px';f.style.top=ny+'px'});
window.addEventListener('mouseup',function(){dr=false});
function UR(r,t,min,max,vel,suf,cb){const v=parseFloat(r.value);t.style.left='0%';t.style.width=((v-min)/(max-min)*100)+'%';vel.textContent=(suf==='°'?parseInt(v):parseFloat(v).toFixed(suf==='x'?2:0))+suf;if(cb)cb(v);}
const rM=document.getElementById('rng-lvlmin'),rX=document.getElementById('rng-lvlmax'),tL=document.getElementById('track-lvl'),vL=document.getElementById('val-lvlrange');
function uL(){let mn=parseInt(rM.value),mx=parseInt(rX.value);if(mn>mx){[mn,mx]=[mx,mn];rM.value=mn;rX.value=mx;}tL.style.left=(mn)+'%';tL.style.width=(mx-mn)+'%';vL.textContent=mn+'-'+mx;S('lvlrange',{min:mn,max:mx});}
rM.addEventListener('input',uL);rX.addEventListener('input',uL);uL();
const rO=document.getElementById('rng-offset'),tO=document.getElementById('track-offset'),vO=document.getElementById('val-offset');
UR(rO,tO,0,360,vO,'°',v=>S('offset',v));rO.addEventListener('input',()=>UR(rO,tO,0,360,vO,'°',v=>S('offset',v)));
const rZ=document.getElementById('rng-zoom'),tZ=document.getElementById('track-zoom'),vZ=document.getElementById('val-zoom');
UR(rZ,tZ,0.2,3,vZ,'x',v=>S('zoom',v));rZ.addEventListener('input',()=>UR(rZ,tZ,0.2,3,vZ,'x',v=>S('zoom',v)));
const rH=document.getElementById('rng-maxhigher'),tH=document.getElementById('track-maxhigher'),vH=document.getElementById('val-maxhigher');
function uH(){const v=parseInt(rH.value);tH.style.width=(v/20*100)+'%';vH.textContent=v>=20?'Max':v;S('maxhigher',v);}
rH.addEventListener('input',uH);uH();
const rL2=document.getElementById('rng-minlower'),tL2=document.getElementById('track-minlower'),vL2=document.getElementById('val-minlower');
function uL2(){const v=parseInt(rL2.value);tL2.style.width=(v/20*100)+'%';vL2.textContent=v>=20?'All':v;S('minlower',v);}
rL2.addEventListener('input',uL2);uL2();
const rS=document.getElementById('rng-safedist'),tS=document.getElementById('track-safedist'),vS=document.getElementById('val-safedist');
UR(rS,tS,1,3,vS,'x',v=>S('safedist',v));rS.addEventListener('input',()=>UR(rS,tS,1,3,vS,'x',v=>S('safedist',v)));
const rA=document.getElementById('rng-avoidstr'),tA=document.getElementById('track-avoidstr'),vA=document.getElementById('val-avoidstr');
UR(rA,tA,0,100,vA,'%',v=>S('avoidstr',v));rA.addEventListener('input',()=>UR(rA,tA,0,100,vA,'%',v=>S('avoidstr',v)));
['bot','killaura','dodgeatk','dodgecd','autorespawn','collectfood','fleedanger','enemyrange','cooldown','tracers','hitboxes','killable','skipteam'].forEach(id=>{
const el=document.getElementById('tgl-'+id);if(el)el.addEventListener('change',function(){S(id,this.checked);});
});
document.getElementById('sel-sprintmode').addEventListener('change',function(){S('sprintmode',parseInt(this.value))});
let waiting=false;
const curDisp=document.getElementById('current-hotkey'),waitStatus=document.getElementById('waiting-status'),changeBtn=document.getElementById('change-hotkey');
function getKeyDisplay(k){const m={'Insert':'Insert','Delete':'Del','Home':'Home','End':'End','PageUp':'PgUp','PageDown':'PgDn','ArrowUp':'\u2191','ArrowDown':'\u2193','ArrowLeft':'\u2190','ArrowRight':'\u2192',' ':'Space','Escape':'Esc'};return m[k]||(k.length===1?k.toUpperCase():k);}
function saveHotkey(k){localStorage.setItem('evoware_toggle_key',k);curDisp.textContent=getKeyDisplay(k);window.parent.postMessage({evoware:1,type:'hotkeyChanged',data:k},'*');}
function loadHotkey(){const s=localStorage.getItem('evoware_toggle_key');curDisp.textContent=getKeyDisplay(s||'Insert');return s||'Insert';}
changeBtn.addEventListener('click',function(){waiting=true;waitStatus.textContent='Press any key...';changeBtn.textContent='Waiting...';});
document.addEventListener('keydown',function(e){if(!waiting)return;e.preventDefault();e.stopPropagation();const k=e.key===' '?' ':e.key;saveHotkey(k);waiting=false;waitStatus.textContent='';changeBtn.textContent='Set';});
loadHotkey();
window.addEventListener('message',function(e){
if(!e.data||!e.data.evoware)return;
const d=e.data;
if(d.type==='updateStats'){
document.getElementById('txt-level').textContent=d.level;
document.getElementById('txt-range').textContent=d.range;
document.getElementById('txt-target').textContent=d.target;
document.getElementById('txt-nearby').textContent=d.nearby;
document.getElementById('txt-botstate').textContent=d.botstate;
document.getElementById('txt-botstate').style.color=d.botstate==='ON'?'#4ade80':'#ef4444';
}
if(d.type==='updateBot'){document.getElementById('tgl-bot').checked=d.checked;document.getElementById('txt-botstate').textContent=d.checked?'ON':'OFF';document.getElementById('txt-botstate').style.color=d.checked?'#4ade80':'#ef4444';}
if(d.type==='updateKillaura'){document.getElementById('tgl-killaura').checked=d.checked;}
if(d.type==='updateAutorespawn'){document.getElementById('tgl-autorespawn').checked=d.checked;}
if(d.type==='updateDodge'){document.getElementById('tgl-dodgeatk').checked=d.checked;}
if(d.type==='updateCollectFood'){document.getElementById('tgl-collectfood').checked=d.checked;}
if(d.type==='updateFlee'){document.getElementById('tgl-fleedanger').checked=d.checked;}
});
<\/script></body></html>`);
doc.close();
let rt, pType, gameCanvas;
let showTracers = false, showHitboxes = false, showKillable = false, showEnemyRange = false, showCooldown = false;
let botActive = false, killaura = false, dodgeAttacks = false, dodgeOnCD = false, autoRespawn = false;
let offset = 135, zoomLevel = 0.5, lvlMin = 0, lvlMax = 100;
let maxHigherLevel = 0, minLowerLevel = 0, safeDistMult = 2.0, avoidStrength = 0.5;
let collectFood = true, sprintMode = 1, fleeDanger = false, skipTeammates = true;
let target = null, targetLevel = 0, menuVisible = true;
let currentAngle = null, rightHeld = false;
let lastAttackTime = 0, lastDodge = 0, lastRespawnTry = 0;
let gameStartTime = 0;
let enemyTimers = new Map(), enemyPrevAngle = new Map(), enemyPrevDist = new Map(), enemySpawnTime = new Map();
let nc = 0, isDead = false, deathTime = 0, boostTimeout = null, toggleKey = 'Insert';
let lastDrawTime = 0, lastStatsTime = 0, lastFoodScanTime = 0, foodScanFrame = 0, cachedFoodPos = null;
let stuckCount = 0, lastSelfPos = { x: 0, y: 0 }, lastSelfPosTime = 0;
function loadToggleKey() { const s = localStorage.getItem('evoware_toggle_key'); if (s) toggleKey = s; }
loadToggleKey();
function getAttackCooldown(lv) {
return lv <= 5 ? 800 : lv <= 10 ? 1100 : lv <= 15 ? 1400 : lv <= 20 ? 1700 :
lv <= 25 ? 2000 : lv <= 30 ? 2300 : lv <= 35 ? 2600 : lv <= 40 ? 2900 :
lv <= 45 ? 3200 : lv <= 50 ? 3500 : lv <= 55 ? 3800 : lv <= 60 ? 4100 :
lv <= 65 ? 4400 : lv <= 70 ? 4700 : lv <= 75 ? 5000 : lv <= 80 ? 5300 :
lv <= 85 ? 5600 : lv <= 90 ? 5900 : lv <= 95 ? 6200 : 6500;
}
function applyZoom() {
if (!rt?.running_layout?.layers) return;
for (const l of rt.running_layout.layers) {
if (l?.scale !== undefined) { l.scale = zoomLevel; if (l.setZIndicesStaleFrom) l.setZIndicesStaleFrom(0); }
}
rt.redraw = true;
}
function computeRange(sz, lv) {
if (!sz) return 0;
let m = 2.18 - Math.min(lv, 100) * 0.0034;
if (m < 1.85) m = 1.85;
if (lv >= 25) m += 0.04;
if (lv >= 45) m += 0.04;
if (lv >= 70) m += 0.05;
return sz * m;
}
function gs(obj) {
if (!obj) return { lv: 0, sz: 0, rng: 0 };
let lv = 0, sz = obj.width || 0;
try {
if (obj.instance_vars) {
let lvs = [];
for (let i = 0; i < obj.instance_vars.length; i++) {
const v = obj.instance_vars[i];
if (typeof v === 'number' && v >= 1 && v <= 200 && Number.isInteger(v)) lvs.push({ i, v });
}
if (lvs.length) {
lvs.sort((a, b) => b.v - a.v);
const early = lvs.filter(l => l.i < 15);
lv = early.length >= 2 ? early[1].v : (early.length === 1 ? early[0].v + 1 : lvs[0].v + 1);
}
}
} catch (e) {}
if (!lv && sz > 0) lv = Math.max(1, Math.floor(sz / 3.5));
return { lv, sz, rng: computeRange(sz, lv) };
}
function getColorTag(obj) {
try {
if (obj.colorRgb !== undefined) return obj.colorRgb;
if (obj.color !== undefined) return obj.color;
if (obj.effects && obj.effects[0] && obj.effects[0].parameters) return obj.effects[0].parameters.join(',');
} catch (e) {}
return null;
}
function isTeammate(self, p) {
if (!skipTeammates) return false;
const a = getColorTag(self), b = getColorTag(p);
if (a === null || b === null) return false;
return a === b;
}
function getPlayer() {
if (!rt?.running_layout || !pType) return null;
const instances = pType.instances;
let self = null, md = Infinity;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p) continue;
const d = Math.hypot(p.x - rt.running_layout.scrollX, p.y - rt.running_layout.scrollY);
if (d < md && d < 500) { md = d; self = p; }
}
return self;
}
function sendStats() {
const self = getPlayer();
const ps = self ? gs(self) : null;
iframe.contentWindow.postMessage({
evoware: 1, type: 'updateStats',
level: ps ? 'Lv.' + ps.lv : '--',
range: ps ? Math.floor(ps.rng) + 'u' : '--',
target: targetLevel > 0 ? 'Lv.' + targetLevel : '--',
nearby: nc,
botstate: botActive ? 'ON' : 'OFF'
}, '*');
}
function simMouse(type, clientX, clientY, button = 0, buttons = 0) {
if (!gameCanvas) return;
const opts = { bubbles: true, cancelable: true, view: window, clientX, clientY, button, buttons };
gameCanvas.dispatchEvent(new MouseEvent(type, opts));
document.dispatchEvent(new MouseEvent(type, opts));
}
function worldToScreen(wx, wy, self) {
const rect = gameCanvas.getBoundingClientRect();
const sc = self.layer.getScale();
return { x: rect.left + rect.width / 2 + (wx - self.x) * sc, y: rect.top + rect.height / 2 + (wy - self.y) * sc };
}
function ensureRightHold(shouldHold) {
if (!gameCanvas) return;
const rect = gameCanvas.getBoundingClientRect();
const cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
if (shouldHold && !rightHeld) { simMouse('mousedown', cx, cy, 2, 2); rightHeld = true; }
else if (!shouldHold && rightHeld) { simMouse('mouseup', cx, cy, 2, 0); rightHeld = false; }
}
function forceReleaseRight() {
if (gameCanvas && rightHeld) {
const rect = gameCanvas.getBoundingClientRect();
simMouse('mouseup', rect.left + rect.width / 2, rect.top + rect.height / 2, 2, 0);
}
rightHeld = false;
}
function updateSpawnTimes() {
if (!pType) return;
const now = performance.now(), aliveUIDs = new Set();
for (let i = 0; i < pType.instances.length; i++) {
const p = pType.instances[i]; if (!p || p.width <= 0) continue;
aliveUIDs.add(p.uid);
if (!enemySpawnTime.has(p.uid)) enemySpawnTime.set(p.uid, now);
}
for (const uid of enemySpawnTime.keys()) { if (!aliveUIDs.has(uid)) enemySpawnTime.delete(uid); }
}
function isRecentlySpawned(uid) {
const spawn = enemySpawnTime.get(uid);
return spawn ? (performance.now() - spawn) < 1200 : false;
}
function performAttack(p, self, ps, sc, vx, vy) {
const dx = p.x - self.x, dy = p.y - self.y;
const at = Math.atan2(dy, dx);
const or = (offset * Math.PI) / 180;
self.angle = ((at + or) % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2);
const ex = vx + dx * sc, ey = vy + dy * sc;
simMouse('mousemove', ex, ey);
simMouse('mousedown', ex, ey, 0, 1);
simMouse('mouseup', ex, ey, 0, 0);
lastAttackTime = performance.now();
}
function killAll() {
const self = getPlayer(); if (!self) return;
const ps = gs(self); if (!ps.sz) return;
const now = performance.now();
if (now - lastAttackTime < getAttackCooldown(ps.lv)) return;
const rect = gameCanvas.getBoundingClientRect();
const sc = self.layer.getScale();
const vx = rect.left + rect.width / 2, vy = rect.top + rect.height / 2;
const instances = pType.instances;
let bestTarget = null, bestDist = Infinity;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isRecentlySpawned(p.uid)) continue;
if (isTeammate(self, p)) continue;
const dist = Math.hypot(p.x - self.x, p.y - self.y);
if (dist > ps.rng * 1.06) continue;
const es = gs(p);
if (es.lv < lvlMin || es.lv > lvlMax) continue;
if (dist < bestDist) { bestDist = dist; bestTarget = p; }
}
if (!bestTarget) { target = null; targetLevel = 0; return; }
target = bestTarget; targetLevel = gs(target).lv;
performAttack(bestTarget, self, ps, sc, vx, vy);
}
function getThreats(self, ps) {
if (!self || !pType) return [];
const threats = [], instances = pType.instances;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isTeammate(self, p)) continue;
const dx = p.x - self.x, dy = p.y - self.y, dist = Math.hypot(dx, dy);
const es = gs(p);
if (dist > es.rng * 1.5) continue;
let isAttacking = false, isBoosting = false;
const angle = p.angle || 0, prevAngle = enemyPrevAngle.get(p.uid);
if (prevAngle !== undefined) {
const nd = Math.min(Math.abs(angle - prevAngle), Math.PI * 2 - Math.abs(angle - prevAngle));
if (nd > 0.15) {
const ata = Math.atan2(dy, dx);
if (Math.abs(angle - ata) < 0.8 || dist < es.rng) isAttacking = true;
}
}
enemyPrevAngle.set(p.uid, angle);
const prevDist = enemyPrevDist.get(p.uid);
if (prevDist !== undefined && (prevDist - dist) > 20 && dist < es.rng * 1.2) isBoosting = true;
enemyPrevDist.set(p.uid, dist);
if (isAttacking || isBoosting || dist < ps.rng * 0.8) threats.push({ dx, dy, dist, es, isAttacking, isBoosting });
}
const alive = new Set();
for (let i = 0; i < pType.instances.length; i++) { const p = pType.instances[i]; if (p?.uid && p.width > 0) alive.add(p.uid); }
for (const uid of enemyPrevAngle.keys()) { if (!alive.has(uid)) enemyPrevAngle.delete(uid); }
for (const uid of enemyPrevDist.keys()) { if (!alive.has(uid)) enemyPrevDist.delete(uid); }
return threats;
}
function tryDodge(self) {
const now = performance.now();
if (!dodgeAttacks || now - lastDodge < 500) return false;
if (dodgeOnCD && now - lastAttackTime < 300) return false;
const ps = gs(self);
const threats = getThreats(self, ps);
if (!threats.length) return false;
let bestThreat = null;
for (const t of threats) { if (!bestThreat || t.dist < bestThreat.dist) bestThreat = t; }
const urgent = bestThreat.isAttacking || bestThreat.isBoosting || bestThreat.dist < ps.rng;
if (!urgent) return false;
const swarm = threats.length > 1;
const ourCdRem = Math.max(0, getAttackCooldown(ps.lv) - (now - lastAttackTime));
if (!swarm && killaura && ourCdRem < bestThreat.dist * 0.5 - 150) return false;
const pushStr = swarm ? 20 : 14;
const pushX = -(bestThreat.dx / bestThreat.dist) * pushStr;
const pushY = -(bestThreat.dy / bestThreat.dist) * pushStr;
const perpX = -bestThreat.dy / bestThreat.dist * pushStr * 0.6;
const perpY = bestThreat.dx / bestThreat.dist * pushStr * 0.6;
self.x += pushX + perpX; self.y += pushY + perpY;
if (rt?.running_layout) { rt.running_layout.scrollX += pushX + perpX; rt.running_layout.scrollY += pushY + perpY; }
if (!botActive) {
if (boostTimeout) clearTimeout(boostTimeout);
const rect = gameCanvas.getBoundingClientRect();
const cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
if (rightHeld) { simMouse('mouseup', cx, cy, 2, 0); rightHeld = false; }
simMouse('mousedown', cx, cy, 2, 2);
boostTimeout = setTimeout(() => { simMouse('mouseup', cx, cy, 2, 0); boostTimeout = null; }, 150);
}
lastDodge = now;
return true;
}
function findPlayButtonRect() {
const all = document.querySelectorAll('div');
for (const el of all) {
if ((el.textContent || '').trim().toUpperCase() !== 'PLAY') continue;
const style = window.getComputedStyle(el);
if (style.display === 'none' || style.visibility === 'hidden') continue;
if (el.offsetParent === null && style.position !== 'fixed') continue;
const r = el.getBoundingClientRect();
if (r.width > 0 && r.height > 0) return r;
}
return null;
}
function clickAt(cx, cy) {
const o = { bubbles: true, cancelable: true, view: window, clientX: cx, clientY: cy, button: 0, buttons: 1 };
document.dispatchEvent(new MouseEvent('mousemove', o));
document.dispatchEvent(new MouseEvent('mousedown', o));
document.dispatchEvent(new MouseEvent('mouseup', o));
document.dispatchEvent(new MouseEvent('click', o));
if (gameCanvas) {
gameCanvas.dispatchEvent(new MouseEvent('mousemove', o));
gameCanvas.dispatchEvent(new MouseEvent('mousedown', o));
gameCanvas.dispatchEvent(new MouseEvent('mouseup', o));
gameCanvas.dispatchEvent(new MouseEvent('click', o));
}
}
function tryRespawn() {
const now = performance.now();
if (now - deathTime < 1100) return;
if (now - lastRespawnTry < 1600) return;
lastRespawnTry = now;
if (!gameCanvas || !gameCanvas.isConnected) { const lc = rt?.canvas; if (lc) gameCanvas = lc; }
if (!gameCanvas) return;
for (const key of [{ key: 'Enter', keyCode: 13 }, { key: ' ', keyCode: 32 }]) {
document.dispatchEvent(new KeyboardEvent('keydown', { ...key, bubbles: true, cancelable: true }));
document.dispatchEvent(new KeyboardEvent('keyup', { ...key, bubbles: true, cancelable: true }));
gameCanvas.dispatchEvent(new KeyboardEvent('keydown', { ...key, bubbles: true, cancelable: true }));
gameCanvas.dispatchEvent(new KeyboardEvent('keyup', { ...key, bubbles: true, cancelable: true }));
}
const tryClick = (attempt) => {
if (getPlayer()) return;
const r = findPlayButtonRect();
if (r) {
clickAt(r.left + r.width / 2, r.top + r.height / 2);
} else if (attempt === 0 && gameCanvas) {
const rect = gameCanvas.getBoundingClientRect();
const cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
[[-40,-80],[0,-40],[0,0],[0,40],[0,80],[60,-40],[-60,-40],[0,120]].forEach(([dx,dy],i) => {
setTimeout(() => { if (!getPlayer()) clickAt(cx + dx, cy + dy); }, i * 50);
});
}
};
for (let i = 0; i < 6; i++) setTimeout(() => tryClick(i), i * 120);
}
const FOOD_COLORS = [
[0xb9,0x5a,0xd9],[0xea,0xea,0xea],[0xfd,0xaf,0xa3],
[0x7e,0xf0,0x88],[0xf8,0xf8,0x9e],[0x91,0xf3,0xf5],[0x7f,0x7f,0x7e]
];
function isFoodColor(r, g, b) {
for (const [fr,fg,fb] of FOOD_COLORS) if (Math.abs(r-fr)<30 && Math.abs(g-fg)<30 && Math.abs(b-fb)<30) return true;
return false;
}
function findClosestFood(self) {
if (!gameCanvas) return null;
let ctx2 = null;
try { ctx2 = gameCanvas.getContext('2d', { willReadFrequently: true }); } catch(e) { return null; }
if (!ctx2) return null;
const rect = gameCanvas.getBoundingClientRect();
const sc = self.layer.getScale();
const cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
const maxRadius = Math.min(500, Math.max(rect.width, rect.height) / 2);
let bestDistSq = Infinity, bestPos = null;
for (let r = 20; r <= maxRadius; r += 20) {
const steps = Math.max(16, Math.floor(r * 0.5));
for (let i = 0; i < steps; i++) {
const angle = (i / steps) * Math.PI * 2;
const px = cx + Math.cos(angle) * r, py = cy + Math.sin(angle) * r;
if (px < 0 || py < 0 || px >= gameCanvas.width || py >= gameCanvas.height) continue;
try {
const d = ctx2.getImageData(px, py, 1, 1).data;
if (isFoodColor(d[0], d[1], d[2])) {
const wx = self.x + (px - cx) / sc, wy = self.y + (py - cy) / sc;
const dsq = (wx-self.x)**2 + (wy-self.y)**2;
if (dsq < bestDistSq) { bestDistSq = dsq; bestPos = { x: wx, y: wy }; }
}
} catch(e) {}
}
if (bestDistSq < r*r) break;
}
return bestPos;
}
function smoothTurn(desired) {
let diff = desired - currentAngle;
while (diff > Math.PI) diff -= Math.PI * 2;
while (diff < -Math.PI) diff += Math.PI * 2;
const maxTurn = 0.35;
if (Math.abs(diff) > maxTurn) diff = Math.sign(diff) * maxTurn;
currentAngle += diff;
currentAngle = ((currentAngle % (Math.PI * 2)) + Math.PI * 2) % (Math.PI * 2);
}
function placeCursor(self) {
const pos = worldToScreen(self.x + Math.cos(currentAngle) * 100, self.y + Math.sin(currentAngle) * 100, self);
simMouse('mousemove', pos.x, pos.y);
}
function checkStuck(self) {
const now = performance.now();
if (now - lastSelfPosTime < 1200) return;
const moved = Math.hypot(self.x - lastSelfPos.x, self.y - lastSelfPos.y);
if (moved < 12 && botActive && !isDead) {
stuckCount++;
currentAngle = Math.random() * Math.PI * 2;
cachedFoodPos = null;
if (stuckCount >= 4) {
self.x += Math.cos(currentAngle) * 20; self.y += Math.sin(currentAngle) * 20;
if (rt?.running_layout) { rt.running_layout.scrollX += Math.cos(currentAngle) * 20; rt.running_layout.scrollY += Math.sin(currentAngle) * 20; }
stuckCount = 0;
}
} else { stuckCount = 0; }
lastSelfPos = { x: self.x, y: self.y }; lastSelfPosTime = now;
}
function autoHunt() {
const self = getPlayer(); if (!self) return;
const ps = gs(self); if (!ps.sz) return;
if (currentAngle === null) currentAngle = self.angle || 0;
checkStuck(self);
const MAP_SIZE = 5000, MARGIN = 400;
let edgePushX = 0, edgePushY = 0;
if (self.x < MARGIN) edgePushX = 1; else if (self.x > MAP_SIZE - MARGIN) edgePushX = -1;
if (self.y < MARGIN) edgePushY = 1; else if (self.y > MAP_SIZE - MARGIN) edgePushY = -1;
const maxTargetLv = maxHigherLevel >= 20 ? Infinity : ps.lv + maxHigherLevel;
const minTargetLv = minLowerLevel >= 20 ? -Infinity : ps.lv - minLowerLevel;
const now = performance.now();
const cd = getAttackCooldown(ps.lv);
const onCD = now - lastAttackTime < cd;
const cdRem = onCD ? cd - (now - lastAttackTime) : 0;
const instances = pType.instances;
let nearbyAttackers = 0, avgX = 0, avgY = 0;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isTeammate(self, p)) continue;
const e_rng = computeRange(p.width || 0, gs(p).lv);
const dist = Math.hypot(p.x - self.x, p.y - self.y);
if (dist < e_rng * 1.15) { nearbyAttackers++; avgX += p.x; avgY += p.y; }
}
if (nearbyAttackers >= 2) {
avgX /= nearbyAttackers; avgY /= nearbyAttackers;
smoothTurn(Math.atan2(self.y - avgY, self.x - avgX));
placeCursor(self); ensureRightHold(true);
target = null; targetLevel = 0; return;
}
if (fleeDanger) {
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isTeammate(self, p)) continue;
const es = gs(p);
if (es.lv <= maxTargetLv) continue;
const dx = self.x - p.x, dy = self.y - p.y, dist = Math.hypot(dx, dy);
if (dist < es.rng * 2.0 && dist > 0.01) {
smoothTurn(Math.atan2(dy, dx)); placeCursor(self);
ensureRightHold(sprintMode !== 2); return;
}
}
}
let bestTarget = null, bestScore = -Infinity;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isRecentlySpawned(p.uid)) continue;
if (isTeammate(self, p)) continue;
const es = gs(p);
if (es.lv < lvlMin || es.lv > lvlMax) continue;
if (es.lv > maxTargetLv || es.lv < minTargetLv) continue;
const dist = Math.hypot(p.x - self.x, p.y - self.y);
const score = (8000 - dist) - Math.max(0, es.lv - ps.lv) * 600;
if (score > bestScore) { bestScore = score; bestTarget = p; }
}
let avoidAngle = 0, avoidWeight = 0;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
if (isTeammate(self, p)) continue;
const es = gs(p);
if (es.lv <= maxTargetLv) continue;
const dx = self.x - p.x, dy = self.y - p.y, dist = Math.hypot(dx, dy);
const safeDist = es.rng * safeDistMult + es.sz * 0.5;
if (dist < safeDist && dist > 0.01) {
const w = (safeDist - dist) / safeDist;
if (w > avoidWeight) { avoidWeight = w * avoidStrength; avoidAngle = Math.atan2(dy, dx); }
}
}
if (onCD && cdRem > 300 && bestTarget) {
const dist = Math.hypot(bestTarget.x - self.x, bestTarget.y - self.y);
if (dist < ps.rng * 1.15) {
smoothTurn(Math.atan2(self.y - bestTarget.y, self.x - bestTarget.x));
placeCursor(self); ensureRightHold(sprintMode !== 2);
target = bestTarget; targetLevel = gs(bestTarget).lv; return;
}
}
let goalAngle;
if (bestTarget) {
target = bestTarget; targetLevel = gs(bestTarget).lv;
goalAngle = Math.atan2(bestTarget.y - self.y, bestTarget.x - self.x);
cachedFoodPos = null;
} else {
target = null; targetLevel = 0;
if (collectFood && (foodScanFrame++ % 10 === 0 || now - lastFoodScanTime > 500)) {
lastFoodScanTime = now; cachedFoodPos = findClosestFood(self);
}
if (collectFood && cachedFoodPos) goalAngle = Math.atan2(cachedFoodPos.y - self.y, cachedFoodPos.x - self.x);
else if (edgePushX !== 0 || edgePushY !== 0) goalAngle = Math.atan2(edgePushY, edgePushX);
else goalAngle = currentAngle + (Math.random() - 0.5) * 0.1;
}
let finalAngle = goalAngle;
if (avoidWeight > 0.05) {
let diff = avoidAngle - goalAngle;
while (diff > Math.PI) diff -= Math.PI * 2;
while (diff < -Math.PI) diff += Math.PI * 2;
finalAngle = goalAngle + diff * Math.min(avoidWeight, 0.85);
}
smoothTurn(finalAngle); placeCursor(self);
let sprint = false;
switch (sprintMode) { case 0: sprint = true; break; case 1: sprint = !!bestTarget; break; case 2: sprint = false; break; }
ensureRightHold(sprint);
if (bestTarget && !killaura) {
const dist = Math.hypot(bestTarget.x - self.x, bestTarget.y - self.y);
if (dist <= ps.rng * 0.97 && !onCD) {
const rect = gameCanvas.getBoundingClientRect();
const sc = self.layer.getScale();
const vx = rect.left + rect.width / 2, vy = rect.top + rect.height / 2;
performAttack(bestTarget, self, ps, sc, vx, vy);
}
}
}
function updateTimers() {
if (!pType || !gameStartTime) return;
const instances = pType.instances;
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p?.uid || p.width <= 0) continue;
if (!enemyTimers.has(p.uid)) { const es = gs(p); enemyTimers.set(p.uid, { cd: getAttackCooldown(es.lv) }); }
}
const alive = new Set();
for (let i = 0; i < instances.length; i++) { const p = instances[i]; if (p?.uid && p.width > 0) alive.add(p.uid); }
for (const uid of enemyTimers.keys()) { if (!alive.has(uid)) enemyTimers.delete(uid); }
}
const esp = document.createElement('canvas');
const ctx = esp.getContext('2d');
esp.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:999998;';
esp.width = innerWidth; esp.height = innerHeight;
document.body.appendChild(esp);
window.addEventListener('resize', () => { esp.width = innerWidth; esp.height = innerHeight; });
function draw() {
const now = performance.now();
if (now - lastDrawTime < 16) return;
lastDrawTime = now;
if (!rt?.running_layout || !pType) return;
const self = getPlayer(); if (!self) return;
const ps = gs(self);
const rect = gameCanvas.getBoundingClientRect();
const sc = self.layer.getScale();
const vx = rect.left + rect.width / 2, vy = rect.top + rect.height / 2;
const instances = pType.instances;
ctx.clearRect(0, 0, esp.width, esp.height);
let nearby = 0;
if (dodgeAttacks) {
const sr = Math.max(ps.rng, 80) * 1.5 * sc;
ctx.beginPath(); ctx.arc(vx, vy, sr, 0, Math.PI * 2);
ctx.strokeStyle = dodgeOnCD ? 'rgba(251,191,36,0.4)' : 'rgba(74,222,128,0.4)';
ctx.lineWidth = 2; ctx.setLineDash([5, 5]); ctx.stroke(); ctx.setLineDash([]);
}
if (killaura || botActive) {
ctx.beginPath(); ctx.arc(vx, vy, ps.rng * sc, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(124,58,237,0.3)'; ctx.lineWidth = 1.5;
ctx.setLineDash([4, 4]); ctx.stroke(); ctx.setLineDash([]);
}
if (target && (killaura || botActive)) {
const angle = self.angle || 0, bl = ps.sz * 0.9 * sc;
const dx = target.x - self.x, dy = target.y - self.y, da = Math.atan2(dy, dx);
ctx.beginPath(); ctx.moveTo(vx, vy); ctx.lineTo(vx + Math.cos(da) * bl, vy + Math.sin(da) * bl);
ctx.strokeStyle = 'rgba(255,255,255,0.3)'; ctx.lineWidth = 1.5; ctx.setLineDash([2, 2]); ctx.stroke();
ctx.beginPath(); ctx.moveTo(vx, vy); ctx.lineTo(vx + Math.cos(angle) * bl, vy + Math.sin(angle) * bl);
ctx.strokeStyle = '#a855f7'; ctx.lineWidth = 3; ctx.setLineDash([]); ctx.stroke();
const or2 = (offset * Math.PI) / 180;
ctx.beginPath(); ctx.moveTo(vx, vy); ctx.lineTo(vx + Math.cos(da + or2) * bl, vy + Math.sin(da + or2) * bl);
ctx.strokeStyle = '#22c55e'; ctx.lineWidth = 2; ctx.setLineDash([3, 3]); ctx.stroke(); ctx.setLineDash([]);
}
for (let i = 0; i < instances.length; i++) {
const p = instances[i]; if (!p || p.uid === self.uid || p.width <= 0) continue;
const es = gs(p); if (es.lv <= 0) continue;
const px = vx + (p.x - self.x) * sc, py = vy + (p.y - self.y) * sc;
const dist = Math.hypot(p.x - self.x, p.y - self.y);
const inRng = dist <= ps.rng, killable = es.lv <= ps.lv, danger = es.lv > ps.lv * 1.3;
if (inRng) nearby++;
if (showCooldown) {
const t = enemyTimers.get(p.uid);
if (t) {
const elapsed = (now - gameStartTime) % t.cd, remaining = t.cd - elapsed, pct = elapsed / t.cd;
ctx.beginPath(); ctx.arc(px, py, 28, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255,255,255,0.08)'; ctx.lineWidth = 2.5; ctx.stroke();
ctx.beginPath(); ctx.arc(px, py, 28, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2 * pct);
ctx.strokeStyle = pct < 0.15 ? '#22c55e' : '#f59e0b'; ctx.lineWidth = 2.5; ctx.stroke();
ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Arial'; ctx.textAlign = 'center';
ctx.fillText((remaining / 1000).toFixed(1) + 's', px, py - 34);
}
}
if (showKillable && inRng) {
ctx.beginPath(); ctx.arc(px, py, 22, 0, Math.PI * 2);
if (killable) {
ctx.shadowColor = '#22c55e'; ctx.shadowBlur = 15;
ctx.strokeStyle = '#22c55e'; ctx.lineWidth = 3; ctx.stroke(); ctx.shadowBlur = 0;
} else if (danger) {
ctx.shadowColor = '#ef4444'; ctx.shadowBlur = 15;
ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 3; ctx.setLineDash([4, 4]); ctx.stroke(); ctx.setLineDash([]); ctx.shadowBlur = 0;
}
}
if (showEnemyRange && es.rng > 0) {
ctx.beginPath(); ctx.arc(px, py, es.rng * sc, 0, Math.PI * 2);
ctx.strokeStyle = dist < es.rng ? 'rgba(255,60,60,0.9)' : 'rgba(255,60,60,0.5)';
ctx.lineWidth = 2; ctx.setLineDash([2, 2]); ctx.stroke(); ctx.setLineDash([]);
}
if (showHitboxes) {
const r = (p.width / 2) * sc * 1.5;
ctx.beginPath(); ctx.arc(px, py, r, 0, Math.PI * 2);
ctx.fillStyle = killable ? 'rgba(34,197,94,0.08)' : 'rgba(124,58,237,0.08)'; ctx.fill();
ctx.strokeStyle = killable ? '#22c55e' : '#a855f7'; ctx.lineWidth = 1; ctx.stroke();
}
if (showTracers) {
ctx.beginPath(); ctx.moveTo(vx, vy); ctx.lineTo(px, py);
ctx.strokeStyle = inRng ? (killable ? 'rgba(34,197,94,0.6)' : 'rgba(168,85,247,0.5)') : 'rgba(168,85,247,0.12)';
ctx.lineWidth = inRng ? 1.5 : 0.5; ctx.stroke();
}
if (target && p.uid === target.uid) {
ctx.beginPath(); ctx.arc(px, py, 26, 0, Math.PI * 2);
ctx.strokeStyle = '#a855f7'; ctx.lineWidth = 2.5; ctx.setLineDash([3, 3]); ctx.stroke(); ctx.setLineDash([]);
ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Arial'; ctx.textAlign = 'center';
ctx.fillText('Lv.' + es.lv, px, py - 30);
}
}
nc = nearby;
}
function enableBotMode(enable) {
if (enable) {
killaura = true; dodgeAttacks = true; autoRespawn = true; collectFood = true; fleeDanger = true;
if (maxHigherLevel === 0) maxHigherLevel = 5;
if (avoidStrength === 0.5) avoidStrength = 0.7;
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateKillaura', checked: true }, '*');
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateDodge', checked: true }, '*');
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateAutorespawn', checked: true }, '*');
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateCollectFood', checked: true }, '*');
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateFlee', checked: true }, '*');
}
botActive = enable;
if (!botActive) { target = null; targetLevel = 0; forceReleaseRight(); }
iframe.contentWindow.postMessage({ evoware: 1, type: 'updateBot', checked: botActive }, '*');
}
function loop() {
try {
if (rt?.running_layout && pType) {
if (!gameStartTime) gameStartTime = performance.now();
applyZoom(); updateTimers(); updateSpawnTimes();
const self = getPlayer();
if (!self) {
if (!isDead) { isDead = true; deathTime = performance.now(); forceReleaseRight(); currentAngle = null; target = null; targetLevel = 0; cachedFoodPos = null; stuckCount = 0; }
ctx.clearRect(0, 0, esp.width, esp.height);
if (autoRespawn) tryRespawn();
} else {
if (isDead) { isDead = false; currentAngle = Math.random() * Math.PI * 2; lastSelfPos = { x: self.x, y: self.y }; lastSelfPosTime = performance.now(); stuckCount = 0; }
updateEntities(self);
const needDraw = showTracers || showHitboxes || showKillable || showEnemyRange || showCooldown || killaura || botActive || dodgeAttacks;
if (needDraw) draw(); else ctx.clearRect(0, 0, esp.width, esp.height);
if (dodgeAttacks) tryDodge(self);
if (killaura) killAll();
if (botActive) autoHunt();
const now = performance.now();
if (now - lastStatsTime > 200) { lastStatsTime = now; sendStats(); }
}
}
} catch (e) {}
requestAnimationFrame(loop);
}
function updateEntities(self) {
if (!pType) return;
const now = performance.now();
for (let i = 0; i < pType.instances.length; i++) {
const p = pType.instances[i]; if (!p || p.width <= 0 || p.uid === self.uid) continue;
}
}
const init = setInterval(() => {
if (window.cr_getC2Runtime && (rt = window.cr_getC2Runtime())) {
clearInterval(init);
gameCanvas = rt.canvas;
for (const t of rt.types_by_index) { if (t?.instvar_sids?.length === 72) { pType = t; break; } }
if (!pType) {
for (const t of rt.types_by_index) {
if (t?.instances?.length > 0) {
const inst = t.instances[0];
if (inst.x !== undefined && inst.y !== undefined && inst.width !== undefined && inst.angle !== undefined) { pType = t; break; }
}
}
}
loop();
}
}, 500);
window.addEventListener('message', function (e) {
if (!e.data || !e.data.evoware) return;
const { type, data } = e.data;
switch (type) {
case 'bot': enableBotMode(data); break;
case 'killaura': killaura = data; if (!killaura && !botActive) { target = null; targetLevel = 0; } break;
case 'dodgeatk': dodgeAttacks = data; if (!dodgeAttacks && boostTimeout) { clearTimeout(boostTimeout); boostTimeout = null; } break;
case 'dodgecd': dodgeOnCD = data; break;
case 'autorespawn': autoRespawn = data; break;
case 'maxhigher': maxHigherLevel = parseInt(data); break;
case 'minlower': minLowerLevel = parseInt(data); break;
case 'safedist': safeDistMult = parseFloat(data); break;
case 'avoidstr': avoidStrength = parseInt(data) / 100; break;
case 'collectfood': collectFood = data; break;
case 'sprintmode': sprintMode = parseInt(data); break;
case 'fleedanger': fleeDanger = data; break;
case 'skipteam': skipTeammates = data; break;
case 'lvlrange': lvlMin = data.min; lvlMax = data.max; break;
case 'enemyrange': showEnemyRange = data; break;
case 'cooldown': showCooldown = data; break;
case 'tracers': showTracers = data; break;
case 'hitboxes': showHitboxes = data; break;
case 'killable': showKillable = data; break;
case 'offset': offset = data; break;
case 'zoom': zoomLevel = data; break;
case 'hotkeyChanged': toggleKey = data; localStorage.setItem('evoware_toggle_key', toggleKey); break;
}
});
document.addEventListener('keydown', function (e) {
if (e.key === toggleKey || e.key === 'Insert') {
e.preventDefault(); e.stopPropagation();
menuVisible = !menuVisible;
iframe.style.opacity = menuVisible ? '1' : '0';
iframe.style.pointerEvents = menuVisible ? 'auto' : 'none';
return;
}
if ((e.key === 'f' || e.key === 'F') &&
document.activeElement?.tagName !== 'INPUT' &&
document.activeElement?.tagName !== 'TEXTAREA') {
e.preventDefault(); e.stopPropagation();
enableBotMode(!botActive);
}
}, true);
})();