<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="52">
  <CheatEntries>
    <CheatEntry>
      <ID>106</ID>
      <Description>"resolver (enable first)"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if NT and NT.timer then NT.timer.destroy() end
NT=NT or {}; NT.cache={}; NT.miss={}; NT.obj=NT.obj or {}
NT.KEYS={rads=0x19945, wep=0x1A027, bwep=0x1895F, ammo=0x188E6, mutpts=0x19DD0, skills=0x19DC5, mutcount=0x19820, hp=0x19822, maxhp=0x1969E, strikes=0x19B76, amax=0x19F2D, hammer=0x194BE}
function NT.ptrsTo(t)
  local ms=createMemScan()
  ms.firstScan(soExactValue, vtQword, rtRounded, string.format("%d",t), "", 0, 0x7fffffffffffffff, "", fsmAligned, "8", false, false, false, false)
  ms.waitTillDone()
  local fl=createFoundList(ms); fl.initialize()
  local r={} for i=0,math.min(fl.Count,5000)-1 do r[#r+1]=tonumber(fl.Address[i],16) end
  fl.destroy(); ms.destroy(); return r
end
function NT.objName(inst)
  local o=readQword(inst+0x90); if not o or o&lt;0x10000 then return nil end
  local s=readQword(o); if not s or s&lt;0x10000 then return nil end
  return readString(s,32)
end
function NT.isInst(p,name)
  if not p or p&lt;0x10000 then return false end
  local o=readQword(p+0x90)
  if NT.obj[name] then if o~=NT.obj[name] then return false end
  elseif NT.objName(p)~=name then return false end
  local m=readQword(p+0x48); local sz=m and readInteger(m)
  return sz and sz&gt;0 and sz&lt;65536
end
function NT.findObj(name)
  if NT.obj[name] then return NT.obj[name] end
  local ms=createMemScan()
  ms.firstScan(soExactValue, vtString, rtRounded, name, "", 0, 0x7fffffffffffffff, "", fsmNotAligned, "1", false, true, false, true)
  ms.waitTillDone()
  local fl=createFoundList(ms); fl.initialize()
  local strs={} for i=0,math.min(fl.Count,200)-1 do local a=tonumber(fl.Address[i],16); if readBytes(a+#name,1)==0 then strs[#strs+1]=a end end
  fl.destroy(); ms.destroy()
  for _,s in ipairs(strs) do
    for _,o in ipairs(NT.ptrsTo(s)) do
      for _,ref in ipairs(NT.ptrsTo(o)) do
        local inst=ref-0x90
        if readQword(inst+0x48) and NT.objName(inst)==name then NT.obj[name]=o; return o end
      end
    end
  end
end
function NT.findInst(name)
  local c=NT.cache[name]
  if NT.isInst(c,name) then return c end
  NT.cache[name]=nil
  local ob=NT.obj[name]
  if ob then
    local nd=readQword(ob+0x50); local ins=nd and nd&gt;0x10000 and readQword(nd+0x10)
    if ins and NT.isInst(ins,name) then NT.cache[name]=ins; return ins end
    return nil
  end
  local b=readQword(getAddress("nuclearthrone.exe")+0x25C5540)
  if b then for o=0,0x200,8 do local p=readQword(b+o); if NT.isInst(p,name) then NT.cache[name]=p; return p end end end
  local g=NT.cache.GameCont
  if name~="GameCont" and g and NT.isInst(g,"GameCont") then
    local h=g; local k=0
    while k&lt;20000 do local p=readQword(h+0x1A8); if not p or p==0 then break end h=p k=k+1 end
    local o=NT.obj[name]; local c=h; local n=0
    while c and c~=0 and n&lt;40000 do n=n+1
      if (o and readQword(c+0x90)==o) or (not o and NT.objName(c)==name) then if NT.isInst(c,name) then NT.cache[name]=c; return c end end
      c=readQword(c+0x1A0) end
    return nil
  end
  if (NT.miss[name] or 0)&gt;getTickCount() then return nil end
  NT.miss[name]=getTickCount()+30000
  local obj=NT.findObj(name); if not obj then return nil end
  for _,ref in ipairs(NT.ptrsTo(obj)) do
    local inst=ref-0x90
    if NT.isInst(inst,name) then NT.cache[name]=inst; return inst end
  end
end
function NT.var(inst,key)
  local m=readQword(inst+0x48); if not m or m&lt;0x10000 then return nil end
  local size=readInteger(m); local mask=readInteger(m+8); local el=readQword(m+0x10)
  if not size or size&lt;=0 or size&gt;65536 or not el then return nil end
  local h=key+1
  local i=h &amp; mask
  for n=0,size-1 do
    local e=el+i*16
    local eh=readInteger(e+12)
    if not eh or eh==0 then return nil end
    if eh==h then local rv=readQword(e); if rv and rv~=0 then return rv end return nil end
    i=(i+1) &amp; mask
  end
  return nil
end
function NT.arr(rv) local a=rv and readQword(rv); return a and readQword(a+8) end
function NT.reg(name,addr) unregisterSymbol(name); if addr then registerSymbol(name,addr,true) end end
function NT.tick()
  local pid=getOpenedProcessID()
  if NT.pid~=pid then NT.pid=pid; NT.obj={}; NT.cache={}; NT.miss={} end
  local gc=NT.findInst("GameCont")
  local pl=NT.findInst("Player")
  NT.reg("NT_gamecont",gc); NT.reg("NT_player",pl)
  NT.reg("NT_rads",   gc and NT.var(gc,NT.KEYS.rads))
  NT.reg("NT_mutpts", gc and NT.var(gc,NT.KEYS.mutpts))
  NT.reg("NT_skills", gc and NT.arr(NT.var(gc,NT.KEYS.skills)))
  NT.reg("NT_wep",    pl and NT.var(pl,NT.KEYS.wep))
  NT.reg("NT_bwep",   pl and NT.var(pl,NT.KEYS.bwep))
  NT.reg("NT_ammo",   pl and NT.arr(NT.var(pl,NT.KEYS.ammo)))
  NT.reg("NT_mutcount", gc and NT.var(gc,NT.KEYS.mutcount))
  NT.reg("NT_hp",      pl and NT.var(pl,NT.KEYS.hp))
  NT.reg("NT_maxhp",   pl and NT.var(pl,NT.KEYS.maxhp))
  NT.reg("NT_strikes", pl and NT.var(pl,NT.KEYS.strikes))
  NT.reg("NT_hammer", pl and NT.var(pl,NT.KEYS.hammer))
end
NT.LISTTABLE=0x23AE2E0
function NT.findMutList()
  local gc=NT.findInst("GameCont"); if not gc then return nil end
  local sk=NT.arr(NT.var(gc,NT.KEYS.skills)); if not sk then return nil end
  local got={}; local ngot=0
  for j=1,29 do if readDouble(sk+j*16)~=0 then got[j]=true; ngot=ngot+1 end end
  local tbl=readQword(getAddress("nuclearthrone.exe")+NT.LISTTABLE)
  local n=readInteger(getAddress("nuclearthrone.exe")+NT.LISTTABLE-8) or 0
  local best=nil
  for i=0,math.min(n,20000)-1 do
    local l=readQword(tbl+i*8)
    if l and l&gt;0x10000 then
      local c=readInteger(l+8); local d=readQword(l+0x18)
      if c and d and c&gt;0 and c&lt;=40 and c==ngot then
        local okAll=true
        for k=0,c-1 do local v=readDouble(d+k*16); if readInteger(d+k*16+12)~=0 or not got[v] then okAll=false break end end
        if okAll then best=l end
      end
    end
  end
  return best
end
function NT.addMutation(id)
  local gc=NT.findInst("GameCont"); local pl=NT.findInst("Player")
  if not gc or not pl then return "no GameCont/Player" end
  local sk=NT.arr(NT.var(gc,NT.KEYS.skills))
  if readDouble(sk+id*16)~=0 then return "already have #"..id end
  local lst=NT.findMutList()
  if not lst then return "mutation list not found (needs at least 1 mutation picked normally)" end
  local c=readInteger(lst+8); local cap=readInteger(lst+0x10); local d=readQword(lst+0x18)
  if c&gt;=cap then return "list full" end
  writeDouble(d+c*16,id); writeInteger(d+c*16+8,0); writeInteger(d+c*16+12,0)
  writeInteger(lst+8,c+1)
  writeDouble(sk+id*16,1)
  local mc=NT.var(gc,NT.KEYS.mutcount); if mc then writeDouble(mc,readDouble(mc)+1) end
  if id==1 then
    local mh=NT.var(pl,NT.KEYS.maxhp); writeDouble(mh,readDouble(mh)+4)
    local h=NT.var(pl,NT.KEYS.hp); writeDouble(h,readDouble(h)+4)
  elseif id==10 then
    local am=NT.arr(NT.var(pl,NT.KEYS.amax))
    if readDouble(am+16)&lt;555 then writeDouble(am+16,555) end
    for j=2,5 do if readDouble(am+j*16)&lt;99 then writeDouble(am+j*16,99) end end
  end
  return "added #"..id
end
NT.KEYS.camx=0x1884E; NT.KEYS.camy=0x1884F
function NT.cursorWorld()
  local pl=NT.cache.Player; if not pl then return nil end
  local hw=findWindow(nil,"Nuclear Throne"); if not hw or hw==0 then return nil end
  if not NT.cbuf then NT.cbuf=createMemoryStream(); NT.cbuf.Size=64 end
  local mem=NT.cbuf.Memory
  executeCodeLocalEx(getAddress("user32.GetClientRect",true),hw,mem)
  local cw,ch=readIntegerLocal(mem+8),readIntegerLocal(mem+12)
  writeIntegerLocal(mem+16,0); writeIntegerLocal(mem+20,0)
  executeCodeLocalEx(getAddress("user32.ClientToScreen",true),hw,mem+16)
  local ox,oy=readIntegerLocal(mem+16),readIntegerLocal(mem+20)
  local sc=math.min(cw/320,ch/240)
  local bx,by=ox+(cw-320*sc)/2, oy+(ch-240*sc)/2
  local mx,my=getMousePos()
  local cx,cy=NT.var(pl,NT.KEYS.camx),NT.var(pl,NT.KEYS.camy)
  if not cx or not cy then return nil end
  return readDouble(cx)+(mx-bx)/sc, readDouble(cy)+(my-by)/sc
end
NT.MODENAMES={["Captain America mode"]=1,["Wonder Woman mode"]=1,["Bullseye mode"]=1,["Jean Grey mode"]=1,["Professor X mode"]=1,["Juggernaut mode"]=1}
function NT.isMode(d,r) if r then local sc=r.Script; return sc and sc:find('NT.solo(memrec)',1,true)~=nil end return NT.MODENAMES[d] or (d and d:find('^Barry Allen mode')) end
function NT.solo(me)
  local al=getAddressList()
  for i=0,al.Count-1 do local r=al[i]
    if r~=me and r.Active and r.Type==vtAutoAssembler and NT.isMode(r.Description,r) then r.Active=false end
  end
end
function NT.baseCaps()
  local sk=getAddressSafe("NT_skills")
  if sk and readDouble(sk+10*16)~=0 then return {555,99,99,99,99} end
  return {255,55,55,55,55}
end
NT.busy=false
NT.tick()
NT.timer=createTimer(nil,false)
NT.timer.Interval=250
NT.timer.OnTimer=function() if NT.busy then return end NT.busy=true pcall(NT.tick) NT.busy=false end
NT.timer.Enabled=true
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if NT and NT.timer then NT.timer.destroy(); NT.timer=nil end
for _,n in ipairs({"NT_gamecont","NT_player","NT_rads","NT_mutpts","NT_skills","NT_wep","NT_bwep","NT_ammo","NT_mutcount","NT_hp","NT_maxhp","NT_strikes","NT_hammer"}) do unregisterSymbol(n) end
{$asm}
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>123</ID>
      <Description>"Bot - enable"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end

CB=CB or {}
if CB.timer then CB.timer.destroy() CB.timer=nil end
CB.log={} CB.q={} CB.state="?" CB.joined=false CB.me=nil CB.err=nil CB.ticks=0
local TEAM,HP=0x19EBC,0x19822
local CHARS={[0]="random",[1]="Fish",[2]="Crystal",[3]="Eyes",[4]="Melting",[5]="Plant",[6]="Y.V.",[7]="Steroids",[8]="Robot",[9]="Chicken",[10]="Rebel",[11]="Horror",[12]="Rogue",[16]="mystery"}
local SKIP={Wall=1,Floor=1,FloorExplo=1,SnowFloor=1,TopSmall=1,TopDecal=1,SnowFlake=1,Bones=1,Detail=1,Scorch=1,ScorchTop=1,Corpse=1,Dust=1,Smoke=1,Debris=1,Rad=1,BigRad=1,ChestOpen=1,Shell=1,BulletHit=1}
local NC={}
local function nameOf(i) local o=readQword(i+0x90); if not o or o&lt;0x10000 then return nil end local n=NC[o]; if n==nil then local sp=readQword(o); n=(sp and sp&gt;0x10000) and (readString(sp,32) or false) or false; NC[o]=n end return n or nil end
local function say(t) pcall(speak,t,false) end
local function now() return getTickCount()/1000 end
local PADASM=[=[
alloc(fakepad,0x200,xinput1_3.XInputGetState)
registersymbol(fakepad)
label(padstate)
registersymbol(padstate)
label(gs_hook)
label(gc_hook)
label(notconn)
fakepad:
gs_hook:
  cmp ecx,0
  jne notconn
  inc dword [padstate]
  mov eax,[padstate]
  mov [rdx],eax
  mov rax,[padstate+4]
  mov [rdx+4],rax
  mov eax,[padstate+0C]
  mov [rdx+0C],eax
  xor eax,eax
  ret
notconn:
  mov eax,48F
  ret
gc_hook:
  cmp ecx,0
  jne notconn
  mov byte [r8],1
  mov byte [r8+1],1
  mov word [r8+2],0
  mov dword [r8+4],FFFFFFFF
  mov dword [r8+8],FFFFFFFF
  mov dword [r8+0C],FFFFFFFF
  mov dword [r8+10],0
  xor eax,eax
  ret
align 10
padstate:
dd 0 0 0 0
xinput1_3.XInputGetState:
  jmp gs_hook
XInputGetCapabilities:
  jmp gc_hook
]=]
local function ensurePad()
  local pid=getOpenedProcessID()
  if CB.pid==pid and CB.PS then return true end
  local gs=getAddressSafe("xinput1_3.XInputGetState"); if not gs then return false end
  local fp=getAddressSafe("fakepad"); local hooked=false
  if fp and readBytes(gs,1)==0xE9 then local rel=readInteger(gs+1,true); hooked=(gs+5+rel)==fp end
  if not hooked then local ok=autoAssemble(PADASM); if not ok then CB.err="pad install failed" return false end end
  CB.PS=getAddress("padstate"); CB.pid=pid; CB.lastPkt=-1; CB.pktT=now()
  return true
end
local function pad() return CB.PS end
local function clamp(v) if v&gt;32767 then return 32767 elseif v&lt;-32767 then return -32767 end return math.floor(v) end
local function stick(off,dx,dy,mag) local ps=pad(); local d=math.sqrt(dx*dx+dy*dy)
  if d&lt;0.001 or mag==0 then writeSmallInteger(ps+off,0); writeSmallInteger(ps+off+2,0) return end
  writeSmallInteger(ps+off,clamp(dx/d*mag)); writeSmallInteger(ps+off+2,clamp(-dy/d*mag)) end
local function buttons(m) writeSmallInteger(pad()+4,m) end
local function trig(l,r) local p=pad(); if l then writeBytes(p+6,l) end if r then writeBytes(p+7,r) end end
local function neutral() local ps=pad(); if ps then writeSmallInteger(ps+4,0); writeBytes(ps+6,0,0); for o=8,14,2 do writeSmallInteger(ps+o,0) end end end
CB.neutral=neutral
local function keepPolled()
  local pk=readInteger(pad()); if pk~=CB.lastPkt then CB.lastPkt=pk; CB.pktT=now() return end
  if now()-CB.pktT&gt;1.0 then local h=findWindow("YYGameMakerYY"); if h then sendMessage(h,0x219,7,0) end; CB.pktT=now() end
end
local function enqueue(dt,f) CB.q[#CB.q+1]={d=dt,f=f} end
local function nudge(gap)
  if now()-(CB.nudgeT or 0)&gt;gap then local h=findWindow("YYGameMakerYY"); if h then sendMessage(h,0x219,7,0) end; CB.nudgeT=now() end
end
local function runQueue()
  if #CB.q==0 then return false end
  local e=CB.q[1]
  if CB.qT and now()-CB.qT&lt;e.d then return true end
  if CB.needPk and readInteger(pad())&lt;CB.needPk and now()-CB.qT&lt;1.0 then nudge(0.08) return true end
  table.remove(CB.q,1); pcall(e.f); CB.qT=now(); CB.needPk=readInteger(pad())+2; nudge(0)
  if #CB.q==0 then CB.qT=nil CB.needPk=nil end
  return true
end
local function screenMap()
  if CB.scr then return CB.scr end
  local h=findWindow("YYGameMakerYY"); if not h then return nil end
  local ms=createMemoryStream(); ms.Size=32; local p=ms.Memory
  executeCodeLocalEx("user32.GetClientRect",h,p)
  local cw,ch=readIntegerLocal(p+8),readIntegerLocal(p+12)
  writeIntegerLocal(p+16,0); writeIntegerLocal(p+20,0); executeCodeLocalEx("user32.ClientToScreen",h,p+16)
  local cx,cy=readIntegerLocal(p+16),readIntegerLocal(p+20); ms.destroy()
  local s=math.min(cw/320,ch/240)
  CB.scr={s=s,ox=cx+(cw-320*s)/2,oy=cy+(ch-240*s)/2}; return CB.scr
end
-- walk all instances once
local function scan()
  if not NT or not NT.cache then return nil end
  local a=NT.cache.GameCont
  if not a or nameOf(a)~="GameCont" then
    if now()-(CB.resT or 0)&gt;5 then CB.resT=now()
      local rr=getAddressList().getMemoryRecordByID(106)
      if rr and not rr.Active then rr.Active=true; CB.log[#CB.log+1]=string.format("%.1f resolver re-enabled",now()) end
    end
    return nil
  end
  local h=a; local k=0
  while k&lt;20000 do local p=readQword(h+0x1A8); if not p or p==0 then break end h=p k=k+1 end
  local r={chars={},players={},walls={},floors={},pshots={},props={},res={},enemies={},names={},shots={},hps={},weps={},haz={},revive={}}
  local c=h; local g=0
  while c and c~=0 and g&lt;40000 do g=g+1
    local n=nameOf(c)
    if n then r.names[n]=true
      if (n:find("Chest") or n:find("Pickup") or n=="Rad" or n=="BigRad") and n~="ChestOpen" and n~="WepPickup" and n~="ReviveChest" then
        local kind=((n=="Rad" or n=="BigRad") and "rad") or (n:find("Ammo") and "ammo") or ((n:find("HP") or n:find("Health")) and "hp") or "other"
        r.res[#r.res+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8),n=n,kind=kind,isChest=n:find("Chest")~=nil} end end
    if n=="Wall" then local x,y=readFloat(c+0xF4),readFloat(c+0xF8); r.walls[(math.floor(x/16)+20000)*100000+math.floor(y/16)+20000]=true
    elseif n=="Floor" or n=="FloorExplo" then local x,y=readFloat(c+0xF4),readFloat(c+0xF8); local fx,fy=math.floor(x/16),math.floor(y/16)
      for i=0,1 do for j=0,1 do r.floors[(fx+i+20000)*100000+fy+j+20000]=true end end
    elseif n=="CharSelect" then r.chars[#r.chars+1]=c
    elseif n=="Player" then r.players[#r.players+1]=c
    elseif n=="WepPickup" then r.weps[#r.weps+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8)}
    elseif n=="ReviveChest" then r.revive[#r.revive+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8)}
    elseif n=="Portal" then r.portal={x=readFloat(c+0xF4),y=readFloat(c+0xF8)}
    elseif n=="Car" or n=="CarVenus" or (n and n:find("Barrel")) then r.haz[#r.haz+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8),n=n}
    elseif n and not SKIP[n] then
      local hrv=NT.var(c,HP)
      if hrv then local trv=NT.var(c,TEAM); local hp=readDouble(hrv)
        if trv and hp and hp&gt;0 then local t=readDouble(trv)
          if t~=2 and t~=0 and not n:find("Missile") then r.enemies[#r.enemies+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8),n=n} elseif t==0 and not n:find("Chest") then r.props[#r.props+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8),n=n} end end
      elseif n:find("HP") or n:find("Health") then
        r.hps[#r.hps+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8)}
      elseif NT.var(c,0x18C29) then
        local trv=NT.var(c,TEAM); local t=trv and readDouble(trv)
        if t and t~=2 then r.shots[#r.shots+1]={c=c,x=readFloat(c+0xF4),y=readFloat(c+0xF8),vx=readFloat(c+0x120) or 0,vy=readFloat(c+0x124) or 0}
        elseif t==2 then local cr=NT.var(c,0x18BB9); r.pshots[#r.pshots+1]={vx=readFloat(c+0x120) or 0,vy=readFloat(c+0x124) or 0,cr=cr and readInteger(cr)} end
      end
    end
    c=readQword(c+0x1A0)
  end
  return r
end
local function los(W,x0,y0,x1,y1)
  local dx,dy=x1-x0,y1-y0; local d=math.sqrt(dx*dx+dy*dy); local n=math.floor(d/6)
  for i=1,n do local x,y=x0+dx*i/n,y0+dy*i/n
    if W[(math.floor(x/16)+20000)*100000+math.floor(y/16)+20000] then return false end end
  return true
end
CB.los=los
-- ===== lobby =====
local function lobby(r)
  if CB.joined then return end
  local sm=screenMap(); if not sm then return end
  local mx,my=getMousePos(); local gx,gy=(mx-sm.ox)/sm.s,(my-sm.oy)/sm.s
  table.sort(r.chars,function(a,b) return readFloat(a+0xFC)&lt;readFloat(b+0xFC) end)
  local best,bd,bi
  for i,c in ipairs(r.chars) do local d=math.abs(readFloat(c+0xFC)+10-gx); if not bd or d&lt;bd then best,bd,bi=c,d,i-1 end end
  local under=(best and bd&lt;10 and gy&gt;180) and bi or nil
  local down=isKeyPressed(VK_LBUTTON)
  if down and not CB.mdown then CB.log[#CB.log+1]=string.format("%.1f click under=%s gx=%.0f gy=%.0f",now(),tostring(under),gx,gy); if under then CB.p1pick=under end end
  CB.mdown=down
  if under~=CB.hov or mx~=CB.hmx or my~=CB.hmy then CB.hov=under; CB.hmx,CB.hmy=mx,my; CB.hovT=now(); CB.warned=false return end
  local hov=under
  if hov and now()-CB.hovT&gt;2.0 then
    if CB.p1pick and hov==CB.p1pick and hov&gt;0 then if not CB.warned then CB.warned=true; say("That one's yours. Point at another.") end return end
    local pushes=hov
    if CB.p1pick and CB.p1pick&gt;0 and CB.p1pick&lt;hov then pushes=hov-1 end
    local img=math.floor(readFloat(best+0xD4)+0.5); local nm=CHARS[img] or "that one"
    CB.joined=true; CB.char=nm; CB.race=nil; CB.raceVotes={}
    say("Joining as "..nm)
    enqueue(0.3,function() buttons(0x10) end); enqueue(0.1,function() buttons(0) end)
    enqueue(0.35,function() end)
    for k=1,pushes do enqueue(0.12,function() stick(8,1,0,30000) end); enqueue(0.1,function() stick(8,0,0,0) end) end
    enqueue(0.25,function() buttons(0x1000) end); enqueue(0.15,function() buttons(0) end)
    enqueue(0.1,function() say("Picked") end)
  end
end
-- ===== game =====
local AMMO={}
do local G={
 [0]={121,67,46,126,101,40,115,74,27,13,88,92,3},
 [1]={17,117,116,108,83,120,103,127,41,39,106,90,89,26,110,4,9,69,71,49,1,81,56,32,65,16,2,86},
 [2]={23,77,10,76,8,114,38,75,22,42,99,91,118,61,5,21,60,25,93,33},
 [3]={11,6,18,43,123,100,105,66,112,113,30,62,12,104,63,31,94},
 [4]={85,14,107,29,78,109,51,73,50,52,84,102,44,122,7,80,79,124,54,37,47,82,15,119,72,95},
 [5]={97,36,53,24,45,98,125,48,55,28,19,20,68,57,58,59,64,35,34,96,70,111,87}}
 for t,l in pairs(G) do for _,id in ipairs(l) do AMMO[id]=t end end end
local MELEE={} for _,id in ipairs({121,67,46,126,101,40,115,74,27,13,88,92,3,24,36,53,37}) do MELEE[id]=true end
local DEFMAX={[0]=0,255,55,55,55,55}
-- ===== weapons =====
local TIERV={S=7,A=6,B=5,C=4,D=3,E=2,F=1,G=1}
local WT={}
for id,l in ("121S 67D 46A 126E 101D 40A 115D 74S 27D 13B 88A 92C 3B 17B 117B 116B 108F 83B 120E 103B 127E 41B 39B 106S 90S 89A 26A 110C 4A 9A 69B 71B 49B 1C 81S 56E 32C 65B 16D 2A 86B 23B 77B 10S 76C 8A 114A 38B 75C 22A 42A 99B 91B 118C 61C 5A 21C 60B 25C 93A 33B 11S 6S 18B 43S 123C 100B 105S 66A 112S 113S 30A 62B 12C 104C 63A 31B 94C 85B 14A 107E 29D 78D 109F 51B 73C 50B 52A 84S 102A 44A 122G 7A 80D 79B 124B 54A 37B 47E 82F 15E 119D 72D 95C 97G 36B 53A 24S 45C 98C 125G 48B 55D 28A 19B 20A 68C 57B 58B 59D 64C 35A 34B 96B 70B 111D 87E"):gmatch("(%d+)(%u)") do WT[tonumber(id)]=TIERV[l] end
local function set(t) local s={} for _,v in ipairs(t) do s[v]=true end return s end
local FAV=set{74,90,11,105}
local NEVER=set{47}
local GOLD=set{101,40,103,127,41,39,42,99,43,123,100,102,44,122,45,98}
local ULTRA=set{92,86,93,94,95,87}
local EXPLO=set{85,14,107,29,78,109,84,102,44,122,7,80,79,124,54,47,82,15,119,95}
local MGUN=set{4,9,83,2,49,41,90,28,96,106,17,103}
local SHOTG=set{5,8,10,42,61,93,75,76,77,117,114,113}
local XBOW=set{6,11,12,43,66,94,105}
CB.WT=WT
local function PP() return CB.PROFILES[CB.profile] or CB.PROFILES.companion end
local function hasSkill(j) local gc=NT.cache.GameCont; local sk=gc and NT.arr(NT.var(gc,NT.KEYS.skills)); return sk and readDouble(sk+j*16)~=0 end
local function wscore(id,other)
  if not id or id==0 then return -50 end
  if NEVER[id] then return -100 end
  local s=WT[id] or 4
  local at=AMMO[id]
  if at==2 and hasSkill(15) then s=s+1 end
  if at==3 and hasSkill(21) then s=s+1 end
  if at==5 and hasSkill(17) then s=s+1 end
  local ch=CB.char
  if ch=="Chicken" and MELEE[id] then s=s+1.5 end
  if ch=="Steroids" and MGUN[id] then s=s+1.5 end
  if ch=="Y.V." then if SHOTG[id] or XBOW[id] then s=s+1.5 end if MELEE[id] then s=s-2 end end
  if other and other~=0 and at and AMMO[other]==at then s=s-PP().same_ammo_penalty end
  return s
end
local function keepScore(id,other)
  local s=wscore(id,other)
  if FAV[id] or id==CB.rebelFav then s=s+100 end
  if CB.char=="Chicken" and MELEE[id] then s=s+3 end
  return s
end
CB.wscore=wscore
local function ammoFrac(me,id)
  local at=AMMO[id]; if not at or at==0 then return 1 end
  local K=NT.KEYS
  local a=NT.arr(NT.var(me,K.ammo)); local m=NT.arr(NT.var(me,K.amax))
  local cur=a and readDouble(a+at*16) or 0
  local mx=m and readDouble(m+at*16); if not mx or mx&lt;=0 or mx&gt;2000 then mx=DEFMAX[at] end
  return cur/mx
end
local function pickupId(c) local v=NT.var(c,NT.KEYS.wep); local d=v and readDouble(v); if d and d&gt;=1 and d&lt;=127 and d==math.floor(d) then return d end return nil end
local function press(mask,T) buttons(mask); CB.btnOff=T+0.12 end
local function openArea(W,x,y,mx,my,px,py)
  local P=PP()
  if (x-mx)^2+(y-my)^2&lt;60*60 then return false end
  if px and (x-px)^2+(y-py)^2&lt;P.explo_partner_clear^2 then return false end
  local cx,cy=math.floor(x/16),math.floor(y/16); local rc=math.ceil(P.explo_wall_clear/16)+1
  for i=-rc,rc do for j=-rc,rc do if W[(cx+i+20000)*100000+cy+j+20000] then
    local wx,wy=(cx+i)*16+8,(cy+j)*16+8; if (wx-x)^2+(wy-y)^2&lt;P.explo_wall_clear^2 then return false end end end end
  return true
end
-- returns loot goal {x,y} or nil; handles swap/pickup presses
local function WM(ctx)
  local P,T,me,r,W=ctx.P,ctx.T,ctx.me,ctx.r,ctx.W
  local mx,my,px,py=ctx.mx,ctx.my,ctx.px,ctx.py
  local K=NT.KEYS
  local wep=ctx.wep; local bwep=math.floor((readDouble(NT.var(me,K.bwep) or 0) or 0)+0.5)
  CB.bwep=bwep
  if CB.char=="Rebel" and CB.rebelFav==nil and wep&gt;0 then CB.rebelFav=wep end
  CB.ignoreW=CB.ignoreW or {}; CB.triedGold=CB.triedGold or {}
  local calm=ctx.visible==0 and not ctx.threat and not ctx.careful
  local calmNear=not ctx.threat
  CB.openOK=true
  if EXPLO[wep] and ctx.tgt and not P.reckless then CB.openOK=openArea(W,ctx.tgt.x,ctx.tgt.y,mx,my,ctx.px,ctx.py) end
  if CB.btnOff then return CB.lootGoal end
  -- pickups visible
  local list={}
  CB.wSeen=CB.wSeen or {}
  for _,w in ipairs(r.weps) do local id=pickupId(w.c); if id then w.id=id; list[w.c]=w; if not CB.wSeen[w.c] then CB.wSeen[w.c]=T end end end
  -- loot in progress
  local L=CB.loot
  if L then
    local w=list[L.c]
    if L.stage=="check" then
      if T&gt;L.t then
        if wep==L.id or bwep==L.id then
          if L.food then CB.foodEat=T+0.25 end
          if L.old and L.old~=0 and wep~=L.old and bwep~=L.old then
            local best,bd
            for c,o in pairs(list) do if o.id==L.old then local d=(o.x-mx)^2+(o.y-my)^2; if not bd or d&lt;bd then best,bd=o,d end end end
            if best then CB.ignoreW[best.c]=true end
            if best and not L.isRegret then
              local p=L.food and 1 or (L.golden and keepScore(L.old,bwep)&gt;keepScore(L.id,bwep)) and 1 or (L.odd and P.odd_regret) or P.regret_chance
              if math.random()&lt;p then CB.regret={c=best.c,id=L.old,at=T+(L.food and 1.0 or (P.regret_min+math.random()*P.regret_rand))} end
            end
          end
        else CB.ignoreW[L.c]=true end
        CB.loot=nil; CB.lootGoal=nil
      end
      return nil
    end
    if not w or not (calm or (calmNear and (w.x-mx)^2+(w.y-my)^2&lt;P.loot_near^2)) then CB.loot=nil; CB.lootGoal=nil return nil end
    local d2=(w.x-mx)^2+(w.y-my)^2
    if d2&lt;10*10 then
      if L.swapFirst and not L.swapped then L.swapped=true; press(0x8000,T); L.waitT=T+0.35; return {w.x,w.y} end
      if L.waitT and T&lt;L.waitT then return {w.x,w.y} end
      L.old=math.floor((readDouble(NT.var(me,K.wep)) or 0)+0.5)
      press(0x4000,T); L.stage="check"; L.t=T+0.45
      if GOLD[L.id] then CB.triedGold[L.id]=true end
      return {w.x,w.y}
    end
    CB.lootGoal={w.x,w.y}; return CB.lootGoal
  end
  -- regret: go back for the one I dropped
  if CB.regret and calm and T&gt;CB.regret.at then
    local w=list[CB.regret.c]
    if w and (w.x-mx)^2+(w.y-my)^2&lt;300*300 and los(W,mx,my,w.x,w.y) then
      CB.loot={c=w.c,id=w.id,swapFirst=false,isRegret=true}; CB.regret=nil; CB.lootGoal={w.x,w.y}; return CB.lootGoal
    elseif not w then CB.regret=nil end
  end
  -- choose a new pickup
  if calmNear and T&gt;(CB.lootScanT or 0) then CB.lootScanT=T+0.5
    local desperate=(ammoFrac(me,wep)&lt;P.ammo_desperate and not MELEE[wep]) and (bwep==0 or (ammoFrac(me,bwep)&lt;P.ammo_desperate and not MELEE[bwep]))
    local function adj(id) if not id or id==0 or MELEE[id] then return 0 end local f=ammoFrac(me,id); if f&lt;P.ammo_desperate then return -P.empty_penalty elseif f&lt;P.ammo_careful then return -P.low_ammo_penalty end return 0 end
    local kw,kb=keepScore(wep,bwep)+adj(wep),keepScore(bwep,wep)+adj(bwep)
    local best,bscore
    CB.validW={}
    for c,w in pairs(list) do
      if w.id~=wep and w.id~=bwep and T-(CB.wSeen[c] or T)&gt;=P.loot_delay and (calm or (w.x-mx)^2+(w.y-my)^2&lt;P.loot_near^2) and not CB.ignoreW[c] and (not CB.regret or c~=CB.regret.c) and (w.x-mx)^2+(w.y-my)^2&lt;P.loot_range^2 and (w.x-px)^2+(w.y-py)^2&lt;P.loot_leash^2 and los(W,mx,my,w.x,w.y) then
        local replaceB=(bwep~=0) and (kb&lt;kw)
        local keepOther=replaceB and wep or bwep
        local cs=wscore(w.id,keepOther)+adj(w.id)*P.pickup_ammo_factor
        local worst=(bwep==0) and -50 or math.min(kw,kb)
        if not NEVER[w.id] then CB.validW=CB.validW or {}; CB.validW[#CB.validW+1]=w end
        local ok=(cs&gt;worst+P.loot_margin) and (cs&gt;=3 or desperate or (bwep==0 and not NEVER[w.id]))
        if GOLD[w.id] and not CB.triedGold[w.id] and worst&lt;90 then ok=true end
        if ok and (not bscore or cs&gt;bscore) then best,bscore=w,cs; best.swapFirst=replaceB end
      end
    end
    local odd=false
    local food=false
    if not best and CB.char=="Robot" and calm and bwep~=0 and #CB.validW&gt;0 then
      local cleared=true for _,e in ipairs(r.enemies) do if (e.x-mx)^2+(e.y-my)^2&lt;P.robot_clear^2 then cleared=false break end end
      local fa=MELEE[wep] and 1 or ammoFrac(me,wep); local fb=MELEE[bwep] and 1 or ammoFrac(me,bwep)
      local benefit=(ctx.hp or 1)&lt;(ctx.mhp or 1) or math.min(fa,fb)&lt;0.8
      if cleared and benefit then local b,bd for _,w in ipairs(CB.validW) do local d=(w.x-mx)^2+(w.y-my)^2; if not bd or d&lt;bd then b,bd=w,d end end
        if b then best=b; best.swapFirst=(kb&lt;kw); food=true end end
    end
    if calm and #CB.validW&gt;0 and math.random()&lt;P.odd_pick_chance then best=CB.validW[math.random(#CB.validW)]; best.swapFirst=(bwep~=0) and (kb&lt;kw); odd=true end
    if best then CB.loot={c=best.c,id=best.id,swapFirst=best.swapFirst,golden=GOLD[best.id],odd=odd,food=food}; CB.lootGoal={best.x,best.y}; return CB.lootGoal end
  end
  -- choose which weapon to hold
  if bwep~=0 and T&gt;(CB.swapT or 0) then
    local fw,fb=ammoFrac(me,wep),ammoFrac(me,bwep)
    local usableB=MELEE[bwep] or fb&gt;P.ammo_desperate
    local why=nil
    if ULTRA[wep] and ctx.visible&lt;4 and usableB then why="ultra" end
    if not why and EXPLO[wep] and ctx.tgt and not CB.openOK and usableB and not EXPLO[bwep] then why="explosive" end
    if not why and not MELEE[wep] and fw&lt;P.ammo_desperate and usableB then why="ammo" end
    if not why and ctx.tgt and math.sqrt(ctx.td)&lt;35 and MELEE[bwep] and not MELEE[wep] and math.random()&lt;0.5 then why="melee-close" end
    if not why and MELEE[wep] and ctx.tgt and math.sqrt(ctx.td)&gt;120 and not MELEE[bwep] and fb&gt;P.ammo_careful then why="gun-far" end
    if not why and ctx.tgt and usableB and not ULTRA[bwep] and T&gt;(CB.varyT or 0) then CB.varyT=T+P.vary_min+math.random()*P.vary_rand; if math.random()&lt;P.vary_chance then why="variety" end end
    if why then CB.swapT=T+1.2; CB.lastSwap=why; press(0x8000,T) end
  end
  return nil
end
CB.WM=WM
CB.keepScore=keepScore
ammoFracG=ammoFrac

-- ===== pathfinding =====
local function ck(cx,cy) return (cx+20000)*100000+cy+20000 end
local function walk(r,cx,cy) local k=ck(cx,cy); return r.floors[k] and not r.walls[k] end
local function fatLos(W,x0,y0,x1,y1)
  local dx,dy=x1-x0,y1-y0; local d=math.sqrt(dx*dx+dy*dy); if d&lt;1 then return true end
  local nx,ny=-dy/d*4,dx/d*4
  return los(W,x0,y0,x1,y1) and los(W,x0+nx,y0+ny,x1+nx,y1+ny) and los(W,x0-nx,y0-ny,x1-nx,y1-ny)
end
local DIRS={{1,0,1},{-1,0,1},{0,1,1},{0,-1,1},{1,1,1.414},{1,-1,1.414},{-1,1,1.414},{-1,-1,1.414}}
local function astar(r,sx,sy,gx,gy,margin,maxc)
  local x0,x1=math.min(sx,gx)-margin,math.max(sx,gx)+margin
  local y0,y1=math.min(sy,gy)-margin,math.max(sy,gy)+margin
  if (x1-x0)&gt;maxc or (y1-y0)&gt;maxc then return nil end
  if not walk(r,gx,gy) then local found=false
    for rr=1,2 do for i=-rr,rr do for j=-rr,rr do if not found and walk(r,gx+i,gy+j) then gx,gy=gx+i,gy+j; found=true end end end end
    if not found then return nil end end
  local heap,hn={},0
  local function push(f,x,y) hn=hn+1; heap[hn]={f,x,y}; local i=hn; while i&gt;1 do local p=i//2; if heap[p][1]&lt;=heap[i][1] then break end heap[p],heap[i]=heap[i],heap[p]; i=p end end
  local function pop() local top=heap[1]; heap[1]=heap[hn]; heap[hn]=nil; hn=hn-1; local i=1
    while true do local l,rr=2*i,2*i+1; local m=i; if l&lt;=hn and heap[l][1]&lt;heap[m][1] then m=l end; if rr&lt;=hn and heap[rr][1]&lt;heap[m][1] then m=rr end; if m==i then break end heap[m],heap[i]=heap[i],heap[m]; i=m end
    return top end
  local g,from={},{}
  local function h(x,y) local ax,ay=math.abs(x-gx),math.abs(y-gy); return math.max(ax,ay)+0.414*math.min(ax,ay) end
  g[ck(sx,sy)]=0; push(h(sx,sy),sx,sy)
  local n=0
  while hn&gt;0 and n&lt;(CB.pathNodes or 4000) do n=n+1
    local t=pop(); local x,y=t[2],t[3]; local k=ck(x,y)
    if x==gx and y==gy then
      local path={} local cur=k
      while cur do local cx=math.floor(cur/100000)-20000; local cy=cur%100000-20000; table.insert(path,1,{cx*16+8,cy*16+8}); cur=from[cur] end
      return path end
    local gk=g[k]
    for _,d in ipairs(DIRS) do local nx,ny=x+d[1],y+d[2]
      if nx&gt;=x0 and nx&lt;=x1 and ny&gt;=y0 and ny&lt;=y1 and walk(r,nx,ny) and (d[3]==1 or (walk(r,x+d[1],y) and walk(r,x,y+d[2]))) then
        local nk=ck(nx,ny); local ng=gk+d[3]
        if not g[nk] or ng&lt;g[nk] then g[nk]=ng; from[nk]=k; push(ng+h(nx,ny),nx,ny) end end end
  end
  return nil
end
local function steerTo(r,P,T,mx,my,gx,gy)
  local function dir(x,y) local dx,dy=x-mx,y-my; local d=math.sqrt(dx*dx+dy*dy)+0.01; return dx/d,dy/d end
  if fatLos(r.walls,mx,my,gx,gy) then CB.pathState="direct"; return dir(gx,gy) end
  local gcx,gcy=math.floor(gx/16),math.floor(gy/16)
  local pc=CB.path
  if not pc or pc.gcx~=gcx or pc.gcy~=gcy or T&gt;pc.t then
    CB.pathNodes=P.path_nodes; local pp=nil; for _,mg in ipairs({P.path_margin,16,40}) do pp=astar(r,math.floor(mx/16),math.floor(my/16),gcx,gcy,mg,P.path_max); if pp then break end end
    pc={p=pp,gcx=gcx,gcy=gcy,t=T+P.path_refresh}; CB.path=pc
  end
  if not pc.p then CB.pathState="nopath"; return dir(gx,gy) end
  for i=#pc.p,1,-1 do local q=pc.p[i]; if fatLos(r.walls,mx,my,q[1],q[2]) then CB.pathState="path"; return dir(q[1],q[2]) end end
  local q=pc.p[math.min(2,#pc.p)]; CB.pathState="path?"; return dir(q[1],q[2])
end
CB.astar=astar
local function findPeek(r,W,mx,my,tx,ty,px,py)
  local cx,cy=math.floor(mx/16),math.floor(my/16)
  local best,bs
  for i=-4,4 do for j=-4,4 do local x,y=cx+i,cy+j
    if walk(r,x,y) then local hx,hy=x*16+8,y*16+8
      if not los(W,hx,hy,tx,ty) and fatLos(W,mx,my,hx,hy) then
        for _,d in ipairs(DIRS) do local nx,ny=x+d[1],y+d[2]
          if walk(r,nx,ny) and (d[3]==1 or (walk(r,x+d[1],y) and walk(r,x,y+d[2]))) then local ox,oy=nx*16+8,ny*16+8
            if los(W,ox,oy,tx,ty) then local s=math.sqrt((hx-mx)^2+(hy-my)^2)+0.3*math.sqrt((hx-px)^2+(hy-py)^2)
              if not bs or s&lt;bs then best,bs={hx=hx,hy=hy,ox=ox,oy=oy},s end end end end end end end end
  return best
end
CB.findPeek=findPeek

-- ===== resource seeking (ammo / health / chests) =====
local function RS(c)
  local P,T,me,r=c.P,c.T,c.me,c.r
  if c.threat then return nil end
  local function gf(id) if not id or id==0 or MELEE[id] then return nil end return ammoFrac(me,id) end
  local fa,fb=gf(c.wep),gf(CB.bwep)
  local af=(fa and fb) and math.min(fa,fb) or fa or fb
  local needA=af and (1-af) or 0
  local needH=1-c.hp/math.max(1,c.mhp)
  local kind,need
  if needA&gt;=needH then kind,need="ammo",needA else kind,need="hp",needH end
  if need&lt;P.res_min_need then kind=nil end
  local radOK=(not kind) and c.visible==0
  if c.visible&gt;0 and (not kind or need&lt;P.res_urgent) then return nil end
  local leash=P.res_leash+need*P.res_leash_gain
  local best,bd
  for _,o in ipairs(r.res) do
    local ok=false
    if kind and o.kind==kind then ok=(o.x-c.px)^2+(o.y-c.py)^2&lt;leash^2 end
    if not ok and radOK and o.kind=="rad" then ok=(o.x-c.px)^2+(o.y-c.py)^2&lt;P.rad_leash^2 end
    if not ok and o.isChest and c.visible==0 and (o.x-c.px)^2+(o.y-c.py)^2&lt;P.explore_leash^2 then ok=true end
    if ok then local d=(o.x-c.mx)^2+(o.y-c.my)^2; if d&lt;P.res_range^2 and (not bd or d&lt;bd) then best,bd=o,d end end
  end
  CB.resKind=best and (best.isChest and "chest:"..best.n or kind) or nil
  return best and {best.x,best.y} or nil
end
-- ===== funzies =====
local RHY=set{4,9,16,17,2,41,49,83,90,103,106,116,1,39,69,71,28,86}
local PATTERNS={"1010111001111001100","101110100010100"}
local function walkable(r,x,y) local k=(math.floor(x/16)+20000)*100000+math.floor(y/16)+20000; return r.floors[k] and not r.walls[k] end
local function crevice(r,mx,my)
  local best,bd
  local cx,cy=math.floor(mx/16),math.floor(my/16)
  for i=-5,5 do for j=-5,5 do local x,y=cx+i,cy+j
    local k=(x+20000)*100000+y+20000
    if r.floors[k] and not r.walls[k] then
      local n=0 for _,d in ipairs({{1,0},{-1,0},{0,1},{0,-1}}) do if r.walls[(x+d[1]+20000)*100000+y+d[2]+20000] then n=n+1 end end
      if n&gt;=3 then local d=i*i+j*j; if not bd or d&lt;bd then best,bd={x*16+8,y*16+8},d end end end end end
  return best
end
local function FZ(c)
  local P,T,r=c.P,c.T,c.r
  if c.solo or c.P.no_funzies then CB.fz=nil return nil end
  local mx,my,px,py=c.mx,c.my,c.px,c.py
  local f=CB.fz
  -- partner idle / lost sight bookkeeping
  if not c.solo then
    local pl=CB.p1last
    if not pl or (px-pl.x)^2+(py-pl.y)^2&gt;9 then CB.p1last={x=px,y=py,t=T} end
    if los(r.walls,mx,my,px,py) then CB.p1seenT=T end
  end
  local p1Idle=(not c.solo) and CB.p1last and T-CB.p1last.t&gt;P.p1_idle
  local lost=(not c.solo) and CB.p1seenT and T-CB.p1seenT&gt;P.lost_time
  local shotsNear=0 for _,s in ipairs(r.shots) do if (s.x-mx)^2+(s.y-my)^2&lt;80*80 then shotsNear=shotsNear+1 end end
  -- end / invalidate current activity
  if f then
    if T&gt;f.untilT or c.threat and f.k~="hide" or (c.visible&gt;0 and f.k~="play" and f.k~="hide") or (f.k=="play" and (not c.tgt or c.coward)) then CB.fz=nil; f=nil end
  end
  -- start new activity
  if not f then
    if shotsNear&gt;=P.hide_shots and T&gt;(CB.hideRollT or 0) then CB.hideRollT=T+3
      if math.random()&lt;P.hide_chance then local cv=crevice(r,mx,my); if cv then f={k="hide",x=cv[1],y=cv[2],untilT=T+1.5+math.random()*1.5} end end
    elseif c.visible&gt;0 and c.visible&lt;=2 and c.tgt and not c.coward and not MELEE[c.wep] and (c.hp or 0)&gt;=(c.mhp or 1)*0.7 and c.tgt.c~=CB.playTried then CB.playTried=c.tgt.c
      if math.random()&lt;P.play_chance then f={k="play",a=math.random()*6.28,dir=(math.random()&lt;0.5) and 1 or -1,untilT=T+2+math.random()*2} end
    elseif c.visible==0 and not c.threat and T&gt;(CB.fzRollT or 0) then CB.fzRollT=T+1
      local pick=nil
      local canGun=not MELEE[c.wep] and (P.reckless or not EXPLO[c.wep])
      if lost then local q=math.random(); pick=(q&lt;0.4) and "pong" or ((q&lt;0.7) and "circles" or "props")
      elseif p1Idle and math.random()&lt;P.idle_activity_chance then
        local opts={"wander","wander","props","orbit","circles","pong","idle","buddy"}
        if canGun and RHY[c.wep] and c.frac&gt;P.rhythm_ammo then opts[#opts+1]="rhythm"; opts[#opts+1]="rhythm" end
        pick=opts[math.random(#opts)]
      else
        local q=math.random()
        if q&lt;P.idle_chance then pick="idle"
        elseif q&lt;P.idle_chance+P.rhythm_walk_chance and canGun and RHY[c.wep] and c.frac&gt;P.rhythm_ammo and not c.solo then pick="rhythm"
        elseif q&lt;P.idle_chance+P.rhythm_walk_chance+P.buddy_chance and canGun and not c.solo then pick="buddy" end
      end
      if pick=="props" and not (canGun and c.frac&gt;P.prop_ammo) then pick=nil end
      if (pick=="rhythm" or pick=="buddy") and not P.reckless then for _,h in ipairs(r.haz) do if (h.x-px)^2+(h.y-py)^2&lt;60*60 then pick=nil break end end end
      if pick then
        f={k=pick,untilT=T+3+math.random()*4,t0=T,cx=mx,cy=my}
        if pick=="idle" then f.untilT=T+1+math.random()*2 end
        if pick=="rhythm" then f.pat=PATTERNS[math.random(#PATTERNS)]; f.untilT=T+#f.pat*P.rhythm_step+0.3; f.moving=not p1Idle end
        if pick=="buddy" then f.untilT=T+0.4+math.random()*0.8 end
        if pick=="wander" then local ox,oy=(c.solo or lost) and mx or px,(c.solo or lost) and my or py
          for _=1,12 do local a,rr=math.random()*6.28,60+math.random()*90; local x,y=ox+math.cos(a)*rr,oy+math.sin(a)*rr; if walkable(r,x,y) then f.x,f.y=x,y break end end
          if not f.x then f=nil end end
        if f and pick=="orbit" then local best,bd
          for _,o in ipairs(r.props) do local d=(o.x-mx)^2+(o.y-my)^2; if d&lt;120*120 and (not bd or d&lt;bd) then best,bd=o,d end end
          if best then f.ox,f.oy=best.x,best.y else
            local cxx,cyy=math.floor(mx/16),math.floor(my/16)
            for i=-4,4 do for j=-4,4 do if not f.ox and r.walls[(cxx+i+20000)*100000+cyy+j+20000] then f.ox,f.oy=(cxx+i)*16+8,(cyy+j)*16+8 end end end end
          if not f.ox then f=nil else f.a=math.atan(my-f.oy,mx-f.ox); f.dir=(math.random()&lt;0.5) and 1 or -1; f.rad=28+math.random()*12 end end
        if f and pick=="pong" then local a=math.random()*6.28; f.dx,f.dy=math.cos(a),math.sin(a) end
        if f and pick=="props" then local best,bd
          for _,o in ipairs(r.props) do local d=(o.x-mx)^2+(o.y-my)^2; if d&lt;160*160 and (not bd or d&lt;bd) and los(r.walls,mx,my,o.x,o.y) then best,bd=o,d end end
          if best then f.tc=best.c; f.tx,f.ty=best.x,best.y else f=nil end end
        CB.fz=f
      end
    end
  end
  CB.fz=f
  if not f then return nil end
  -- run activity
  local o={k=f.k}
  local function toward(x,y,sp) local dx,dy=x-mx,y-my; local d=math.sqrt(dx*dx+dy*dy)+0.01; if d&lt;3 then return 0,0 end return dx/d*(sp or 1),dy/d*(sp or 1) end
  if f.k=="hide" then o.vx,o.vy=toward(f.x,f.y); o.move=true
  elseif f.k=="play" then f.a=f.a+0.06*f.dir; local tx,ty=c.tgt.x+math.cos(f.a)*P.play_radius,c.tgt.y+math.sin(f.a)*P.play_radius; o.vx,o.vy=toward(tx,ty); o.move=true; o.noShoot=true; o.aim={x=c.tgt.x,y=c.tgt.y}
  elseif f.k=="idle" then o.vx,o.vy=0,0; o.move=true; o.noShoot=true
  elseif f.k=="wander" then local ux,uy=steerTo(r,P,T,mx,my,f.x,f.y); o.vx,o.vy=ux*0.8,uy*0.8; o.move=true; if (f.x-mx)^2+(f.y-my)^2&lt;100 then f.untilT=T end
  elseif f.k=="circles" then local a=(T-f.t0)*3.0; local tx,ty=f.cx+math.cos(a)*18,f.cy+math.sin(a)*18; o.vx,o.vy=toward(tx,ty,0.7); o.move=true
  elseif f.k=="orbit" then f.a=f.a+0.05*f.dir; local tx,ty=f.ox+math.cos(f.a)*f.rad,f.oy+math.sin(f.a)*f.rad; o.vx,o.vy=toward(tx,ty); o.move=true
  elseif f.k=="pong" then if (CB.stuck or 0)&gt;4 then local a=math.atan(-f.dy,-f.dx)+(math.random()-0.5)*2.4; f.dx,f.dy=math.cos(a),math.sin(a); CB.stuck=0 end; o.vx,o.vy=f.dx,f.dy; o.move=true
  elseif f.k=="props" then local alive=false for _,p in ipairs(r.props) do if p.c==f.tc then alive=true; f.tx,f.ty=p.x,p.y end end
    if not alive then CB.fz=nil return nil end; o.aim={x=f.tx,y=f.ty}; o.fireNormal=true
  elseif f.k=="rhythm" then local i=math.floor((T-f.t0)/P.rhythm_step)+1; local bit=f.pat:sub(i,i); o.aim={x=px,y=py}; o.fireBit=(bit=="1"); if not f.moving then o.vx,o.vy=0,0; o.move=true end
  elseif f.k=="buddy" then o.aim={x=px,y=py}; o.fireBit=math.floor((T-f.t0)/0.12)%2==0
  end
  return o
end
CB.FZ=FZ

ROGUE_BIG={BanditBoss=true,ScrapBoss=true,LilHunter=true,FrogQueen=true,HyperCrystal=true,TechnoMancer=true,Nothing=true,Nothing2=true,BigFish=true,OasisBoss=true}
CB.PROFILES=CB.PROFILES or {}
CB.PROFILES.companion={
  -- shooting
  range_x=200, range_y=140, range_r=220,        -- how far I shoot (px)
  react_min=0.15, react_rand=0.25,              -- delay before first shot at a new target (s)
  aim_smooth=0.18, aim_idle_smooth=0.06,        -- how fast the crosshair turns (0..1 per tick)
  -- dodging
  dodge_range=70, dodge_line=14, dodge_time=0.25, dodge_speed=1.3,
  dodge_react_min=0.08, dodge_react_rand=0.12, dodge_miss=0.12,
  dodge_perp=0.6,                               -- 1 = purely sideways, 0 = straight away
  fish_roll_range=30, fish_roll_cd=0.9,
  -- ammo
  ammo_careful=0.20, careful_close_to=110, burst_min=2, burst_rand=2, burst_pause=0.5, burst_pause_rand=0.4,
  ammo_desperate=0.05, desperate_range=60,
  -- melee
  melee_shot_range=45, melee_swing_range=30, melee_cooldown=0.5, melee_back_time=0.35,
  melee_react_min=0.05, melee_react_rand=0.10, melee_aim_smooth=0.35,
  -- low HP
  low_hp_frac=0.5, low_hp_min=2, low_hp_recover=0.6, low_careful_chance=0.97,
  low_open_max_enemies=3, low_threat_range=50, hp_seek_range=260, hp_go_melee=0.9, hp_go_gun=0.6,
  -- following
  follow_close=0.6, follow_behind=0.3, behind_off=45, ahead_off=60,
  follow_slack=45, follow_max=110, sprint_dist=180, mode_min=4, mode_rand=5,
  crowd_backoff=80, strafe=0.6, strafe_pause=0.25,
  -- weapons
  loot_range=200, loot_leash=260, loot_margin=0.5, loot_near=50, same_ammo_penalty=2.5, empty_penalty=4, low_ammo_penalty=1.5, pickup_ammo_factor=0.25,
  -- character specials
  car_safe=120, car_safe_p1=70, car_enemy_radius=50, car_enemies=1, melee_haz_radius=40, venus_clear=20,
  revive_clear=120, peek_chance=0.5, peek_shots=3, peek_hide=0.9, peek_out=0.6, peek_max_time=12, melee_stop=26, contact_avoid=18, robot_spare_range=150, robot_last_hp=0.3, robot_tb_last_hp=0.5, robot_clear=250, rogue_hp_value=40, strike_safe=80,
  melee_crowd_max=3, haz_self_safe=120, explo_wall_clear=50, explo_partner_clear=60, shotdir_time=2, shotdir_off=70, solo_engage=110, rad_leash=150, path_nodes=4000,
  -- priorities
  bigfirst=0.8, ammo_coward=0.25, loot_delay=2, odd_pick_chance=0.004, odd_regret=0.6,
  res_min_need=0.15, res_urgent=0.6, res_leash=150, res_leash_gain=300, res_range=300, explore_leash=180,
  -- funzies
  p1_idle=2, lost_time=30, hide_shots=6, hide_chance=0.35, play_chance=0.25, play_radius=50,
  idle_activity_chance=0.5, idle_chance=0.02, rhythm_walk_chance=0.01, buddy_chance=0.005,
  rhythm_ammo=0.4, rhythm_step=0.13, prop_ammo=0.4, path_margin=6, path_max=48, path_refresh=0.25,
  sp_shot_radius=80, crystal_shots=4, crystal_hold=0.4,
  eyes_chance=0.33, eyes_min=1.5, eyes_rand=1.5,
  melting_cd=1.5, plant_range=150, plant_cd=3,
  robot_eat_score=4, robot_cd=2, rebel_hp=0.7, rebel_enemies=2, rebel_cd=8,
  horror_enemies=4, horror_hp=0.5, rogue_cluster=3, rogue_cd=5,
  crystal_tb_maxhold=1.5, crystal_tp_cd=3, crystal_tp_dist=90, crystal_tp_crowd_r=70, crystal_tp_crowd_n=3, crystal_tp_far=220,
  yv_tb_frac=0.4, yv_tb_enemies=2, robot_tb_eat_score=5, robot_tb_hp=0.5,
  char_override={ Melting={low_hp_min=1, low_hp_frac=0.5, low_careful_chance=1.0, low_open_max_enemies=2, crowd_backoff=100, behind_off=60, follow_behind=0.5, follow_close=0.4} },
  regret_chance=0.15, regret_min=3, regret_rand=5,
  vary_min=6, vary_rand=6, vary_chance=0.25,
}
local C=CB.PROFILES.companion
C.aim_align=C.aim_align or 0.97
local function persona(t) return setmetatable(t,{__index=C}) end
CB.PROFILES.shadow=persona{ follow_close=0.9, follow_behind=0.1, follow_slack=30, shotdir_off=50, copy_target=true,
  idle_chance=0.005, rhythm_walk_chance=0.003, buddy_chance=0.001, play_chance=0.05, idle_activity_chance=0.2, odd_pick_chance=0.001 }
CB.PROFILES.coward=persona{ peek_chance=1.0, low_hp_frac=0.7, low_careful_chance=1.0, low_open_max_enemies=1, crowd_backoff=120, behind_off=70,
  follow_close=0.3, follow_behind=0.7, dodge_miss=0.03, dodge_react_min=0.05, dodge_range=90, hide_chance=0.8, hide_shots=3,
  ammo_coward=0.4, melee_crowd_max=1, play_chance=0 }
CB.PROFILES.hunter=persona{ peek_chance=0.3, range_x=230, range_y=160, range_r=260, careful_close_to=80, crowd_backoff=50, low_hp_frac=0.3,
  low_careful_chance=0.7, melee_crowd_max=4, follow_close=0.4, follow_behind=0.1, ahead_off=90, bigfirst=0.95, play_chance=0.1, solo_engage=150 }
CB.PROFILES.predator=persona{ peek_chance=1.0, no_funzies=true, play_chance=0, odd_pick_chance=0, regret_chance=0,
  react_min=0.05, react_rand=0.05, aim_smooth=0.35, aim_align=0.995, dodge_miss=0, dodge_react_min=0.03, dodge_react_rand=0.04,
  bigfirst=1.0, low_hp_frac=0.4, low_careful_chance=1.0, burst_min=1, burst_rand=1 }
CB.PROFILES.spelunker=persona{ explore_leash=400, rad_leash=350, res_leash=300, loot_leash=450, loot_range=280, odd_pick_chance=0.02,
  p1_idle=1, idle_activity_chance=0.9, follow_slack=70, follow_max=200 }
CB.PROFILES.sadist=persona{ peek_chance=0, reckless=true, shoot_barrels=true, car_safe=0, car_safe_p1=0, car_enemies=1, play_chance=0.5, buddy_chance=0.02 }
CB.PROFILES.joker=persona{ peek_chance=0.3, shoot_barrels=true, car_safe=100, car_safe_p1=150, idle_chance=0.04, rhythm_walk_chance=0.04, buddy_chance=0.02,
  play_chance=0.5, odd_pick_chance=0.03, odd_regret=0.8, regret_chance=0.4, idle_activity_chance=0.9, p1_idle=1.5 }
CB.PERSONA_ORDER={"companion","shadow","coward","hunter","predator","spelunker","sadist","joker","random"}
function CB.applyPersona()
  local ch=CB.personaChoice or "companion"
  if ch=="random" then local l={} for _,n in ipairs(CB.PERSONA_ORDER) do if n~="random" then l[#l+1]=n end end; CB.profile=l[math.random(#l)] else CB.profile=ch end
  CB.Pc=nil
end
local function personaHeader() local al=getAddressList() for i=0,al.Count-1 do local m=al[i]; if m.Description:find("^Bot personality") then return m end end end
function CB.setPersona(name,quiet)
  if CB.inSet then return end
  CB.inSet=true
  CB.personaChoice=name; CB.applyPersona()
  local h=personaHeader()
  if h then h.Description="Bot personality: "..name
    for j=0,h.Count-1 do local ch=h.Child[j]; local want=(ch.Description==name); if ch.Active~=want then pcall(function() ch.Active=want end) end end end
  CB.inSet=false
  if not quiet then if name=="random" then say("Random. This time I'm "..CB.profile) else say(name..", ready.") end end
end
function CB.cyclePersona()
  local cur=CB.personaChoice or "companion"; local idx=1
  for i,n in ipairs(CB.PERSONA_ORDER) do if n==cur then idx=i end end
  CB.setPersona(CB.PERSONA_ORDER[idx%#CB.PERSONA_ORDER+1])
end
do local h=personaHeader(); local nm=h and h.Description:match("^Bot personality: (%a+)")
  CB.personaChoice=nm or CB.personaChoice or "companion"; CB.applyPersona() end

local function identify(r)
  if #r.players&lt;2 then return end
  local by={} local RACE=0x19695
  if CB.race then for _,p in ipairs(r.players) do local v=NT.var(p,RACE); if v and readDouble(v)==CB.race then by[0]=p else by[1]=p end end
  else for _,p in ipairs(r.players) do local v=NT.var(p,0x1892A); local d=v and readDouble(v); if d then by[d]=p end end end
  if #r.players==2 and by[0] and by[1] then
    CB.me=by[0]; CB.p1=by[1]; CB.idE={}; CB.idPrev={}; CB.idN=0; CB.idPos=nil; CB.ignoreW={}; CB.loot=nil; CB.regret=nil; CB.lootGoal=nil
    if not CB.greeted then CB.greeted=true; say("I'm in. Right behind you.") end
    return end
  neutral()
  if CB.idPos then local cur={} for _,p in ipairs(r.players) do cur[p]=true end for _,e in ipairs(CB.idPos) do if not cur[e.p] then CB.idPos=nil break end end end
  if not CB.idPos or #CB.idPos~=#r.players then CB.idPos={} for i,p in ipairs(r.players) do CB.idPos[i]={p=p,x=readFloat(p+0xF4),y=readFloat(p+0xF8)} end return end
  for _,e in ipairs(CB.idPos) do local x,y=readFloat(e.p+0xF4),readFloat(e.p+0xF8)
    if x and (x-e.x)^2+(y-e.y)^2&gt;9 then
      CB.p1=e.p; for _,o in ipairs(CB.idPos) do if o.p~=e.p then CB.me=o.p end end
      CB.idPos=nil; CB.ignoreW={}; CB.loot=nil; CB.regret=nil; CB.lootGoal=nil
      if CB.me and not CB.greeted then CB.greeted=true; say("I'm in. Right behind you.") end
      return end end
end
local function game(r)
  local P0=CB.PROFILES[CB.profile] or CB.PROFILES.companion
  local OV=P0.char_override and P0.char_override[CB.char or ""]
  local P=P0
  if OV then CB.Pc=CB.Pc or {}; local key=(CB.profile or "")..(CB.char or ""); if not CB.Pc[key] then CB.Pc[key]=setmetatable(OV,{__index=P0}) end; P=CB.Pc[key] end
  local nP=#r.players
  if CB.lastN==2 and nP==1 then
    if r.players[1]==CB.me then CB.solo=true; CB.log[#CB.log+1]=string.format("%.1f partner down, solo",now()); say("You're down. I'll find a way to bring you back.")
    else CB.botDead=true; CB.log[#CB.log+1]=string.format("%.1f bot down",now()) end
  end
  if nP==2 and (CB.solo or CB.botDead) then CB.solo=false; CB.botDead=false; CB.me=nil; CB.p1=nil; CB.idE={}; CB.idPrev={}; CB.idN=0; CB.log[#CB.log+1]=string.format("%.1f revived",now()); say("Back together.") end
  if nP&gt;0 then CB.lastN=nP end
  if CB.botDead then neutral() return end
  local solo=CB.solo and nP==1
  if solo then CB.me=r.players[1]; CB.p1=nil end
  local present=false; for _,p in ipairs(r.players) do if p==CB.me then present=true end end
  if not solo and (not present or not CB.p1) then CB.me=nil; identify(r) return end
  -- continuous identity check: who responds to my stick?
  if not solo then
  CB.idE=CB.idE or {}; CB.idPrev=CB.idPrev or {}
  local cx,cy=CB.cmdX or 0,CB.cmdY or 0; local cmdOn=(cx*cx+cy*cy)&gt;0.04
  for _,p in ipairs(r.players) do
    local x,y=readFloat(p+0xF4),readFloat(p+0xF8); local pr=CB.idPrev[p]
    if pr then local dx,dy=x-pr[1],y-pr[2]; local dm=math.sqrt(dx*dx+dy*dy); local e
      if cmdOn then local cl=math.sqrt(cx*cx+cy*cy); if dm&gt;0.4 then e=math.sqrt((dx/dm-cx/cl)^2+(dy/dm-cy/cl)^2)/2 else e=0.6 end
      else e=(dm&gt;0.4) and 1 or 0 end
      CB.idE[p]=(CB.idE[p] or 0)*0.97+e
    end
    CB.idPrev[p]={x,y}
  end
  CB.idN=(CB.idN or 0)+1
  if CB.race then local v=CB.me and NT.var(CB.me,0x19695); if v and readDouble(v)~=CB.race then CB.race=nil; CB.raceVotes={}; CB.log[#CB.log+1]=string.format("%.1f tag mismatch, back to movement check",now()) end end
  if not CB.race and #r.players==2 and CB.idN&gt;25 then
    local other=(r.players[1]==CB.me) and r.players[2] or r.players[1]
    if false and CB.idN&gt;200 and (CB.idE[other] or 0)-(CB.idE[CB.me] or 0)&gt;8 then local v=NT.var(CB.me,0x19695); local rc=v and readDouble(v)
      if rc then CB.raceVotes=CB.raceVotes or {}; CB.raceVotes[rc]=(CB.raceVotes[rc] or 0)+1; CB.idN=0
        if CB.raceVotes[rc]&gt;=3 then CB.race=rc; CB.log[#CB.log+1]=string.format("%.1f learned race %d",now(),rc) end end end
    if (CB.idE[CB.me] or 0)-(CB.idE[other] or 0)&gt;6 then
      CB.p1=CB.me; CB.me=other; CB.idN=0; CB.idE={}
      CB.log[#CB.log+1]=string.format("%.1f identity corrected",now())
      CB.loot=nil; CB.lootGoal=nil; CB.regret=nil
    end
  end
  end
  local me,p1=CB.me,CB.p1
  local K=NT.KEYS
  local function rd(i,k) local v=NT.var(i,k); return v and readDouble(v) end
  local hp,mhp=rd(me,HP) or 0, rd(me,K.maxhp) or 8
  if hp&lt;=0 and CB.char~="Chicken" then neutral() return end
  CB.headless=(hp&lt;=0)
  local mx,my=readFloat(me+0xF4),readFloat(me+0xF8)
  local px,py
  if not solo then px,py=readFloat(p1+0xF4),readFloat(p1+0xF8)
  else
    local P0=P; P=setmetatable({follow_slack=8,follow_max=8,behind_off=0,ahead_off=0,loot_leash=400,path_max=140,path_refresh=1.0,path_nodes=20000,strafe_pause=0,melee_crowd_max=4},{__index=P0})
    local mx0,my0=readFloat(me+0xF4),readFloat(me+0xF8)
    local function near(list) local b,bd for _,o in ipairs(list) do local d=(o.x-mx0)^2+(o.y-my0)^2; if not bd or d&lt;bd then b,bd=o,d end end return b,bd end
    local rc=near(r.revive)
    local busy=false for _,e in ipairs(r.enemies) do if (e.x-mx0)^2+(e.y-my0)^2&lt;P.revive_clear^2 and los(r.walls,mx0,my0,e.x,e.y) then busy=true break end end
    CB.stillChk=CB.stillChk or {x=mx0,y=my0,t=now()}
    if now()-CB.stillChk.t&gt;1 then
      if (mx0-CB.stillChk.x)^2+(my0-CB.stillChk.y)^2&lt;16 then local a=math.random()*6.28; CB.soloKick={math.cos(a),math.sin(a),now()+0.8} end
      CB.stillChk={x=mx0,y=my0,t=now()} end
    local visAny=false for _,e in ipairs(r.enemies) do if (e.x-mx0)^2+(e.y-my0)^2&lt;200*200 and los(r.walls,mx0,my0,e.x,e.y) then visAny=true break end end
    if rc and not busy then px,py=rc.x,rc.y; CB.soloGoal="revive"
    elseif rc then px,py=mx0,my0; CB.soloGoal="clearing"
    elseif visAny then
      local e,ed=nil,nil for _,o in ipairs(r.enemies) do local d=(o.x-mx0)^2+(o.y-my0)^2; if d&lt;200*200 and los(r.walls,mx0,my0,o.x,o.y) and (not ed or d&lt;ed) then e,ed=o,d end end
      if e and ed&gt;P.solo_engage^2 then px,py=e.x,e.y else px,py=mx0,my0 end; CB.soloGoal="fight"
    elseif (function() for _,o in ipairs(r.res) do if o.isChest then return true end end end)() then
      local b,bd for _,o in ipairs(r.res) do if o.isChest then local d=(o.x-mx0)^2+(o.y-my0)^2; if not bd or d&lt;bd then b,bd=o,d end end end
      px,py=b.x,b.y; CB.soloGoal="chest"
    else local e,ed=near(r.enemies)
      if e then if ed&gt;80*80 then px,py=e.x,e.y else px,py=mx0,my0 end; CB.soloGoal="hunt"
      elseif r.portal then px,py=r.portal.x,r.portal.y; CB.soloGoal="portal"
      else
        local T0=now()
        if not CB.wdir or T0&gt;(CB.wdirT or 0) or (CB.stuck or 0)&gt;6 then local a=math.random()*math.pi*2; CB.wdir={math.cos(a),math.sin(a)}; CB.wdirT=T0+3+math.random()*4 end
        px,py=mx0+CB.wdir[1]*60,my0+CB.wdir[2]*60; CB.soloGoal="wander"
      end
    end
    if CB.soloKick and now()&lt;CB.soloKick[3] then px,py=mx0+CB.soloKick[1]*40,my0+CB.soloKick[2]*40; CB.soloGoal="unstick" end
  end
  local W=r.walls
  local T=now()
  if CB.rollOff and T&gt;CB.rollOff then trig(0,nil); CB.rollOff=nil end
  local wep=math.floor((rd(me,K.wep) or 0)+0.5)
  local melee=MELEE[wep]
  local at=AMMO[wep] or 1
  local frac=1
  if at&gt;0 then
    local a=NT.arr(NT.var(me,K.ammo)); local m=NT.arr(NT.var(me,K.amax))
    local cur=a and readDouble(a+at*16) or 0
    local mx2=m and readDouble(m+at*16); if not mx2 or mx2&lt;=0 or mx2&gt;2000 then mx2=DEFMAX[at] end
    frac=cur/mx2
  end
  CB.frac=frac; CB.wep=wep; CB.hp=hp
  CB.trail=CB.trail or {}
  local lt=CB.trail[#CB.trail]
  if not lt or (px-lt[1])^2+(py-lt[2])^2&gt;256 then CB.trail[#CB.trail+1]={px,py}; if #CB.trail&gt;10 then table.remove(CB.trail,1) end end
  local tdx,tdy=0,0
  if #CB.trail&gt;=3 then tdx=CB.trail[#CB.trail][1]-CB.trail[1][1]; tdy=CB.trail[#CB.trail][2]-CB.trail[1][2]; local l=math.sqrt(tdx*tdx+tdy*tdy); if l&gt;1 then tdx,tdy=tdx/l,tdy/l else tdx,tdy=0,0 end end
  if T&gt;(CB.modeT or 0) then CB.modeT=T+P.mode_min+math.random()*P.mode_rand; local q=math.random(); CB.fmode=(q&lt;P.follow_close) and "close" or ((q&lt;P.follow_close+P.follow_behind) and "behind" or "ahead") end
  local function inRange(x,y) local dx,dy=x-mx,y-my; return math.abs(dx)&lt;P.range_x and math.abs(dy)&lt;P.range_y and dx*dx+dy*dy&lt;P.range_r*P.range_r end
  local tgt,td,close,cd; local visible=0; local vis={}
  for _,e in ipairs(r.enemies) do local dx,dy=e.x-mx,e.y-my; local d=dx*dx+dy*dy
    if d&lt;P.crowd_backoff^2 and (not cd or d&lt;cd) then close,cd=e,d end
    if inRange(e.x,e.y) and los(W,mx,my,e.x,e.y) then visible=visible+1; e.d2=d; vis[#vis+1]=e; if not td or d&lt;td then tgt,td=e,d end end end
  if visible&gt;=2 then
    local lk=nil for _,e in ipairs(vis) do if e.c==CB.lockC then lk=e end end
    if not lk or T&gt;(CB.lockT or 0) then CB.lockT=T+1+math.random()
      if math.random()&lt;P.bigfirst then local b,bm for _,e in ipairs(vis) do local v=NT.var(e.c,K.maxhp); local m=(v and readDouble(v) or 1)/(math.sqrt(e.d2)+16); if not bm or m&gt;bm then b,bm=e,m end end; lk=b else lk=nil end
      CB.lockC=lk and lk.c end
    if lk then tgt,td=lk,lk.d2 end
  end
  if P.copy_target and not solo and CB.p1shot and T-CB.p1shot[3]&lt;1.5 and #vis&gt;0 then
    local b,bs for _,e in ipairs(vis) do local ex,ey=e.x-px,e.y-py; local l=math.sqrt(ex*ex+ey*ey)+0.01; local s=(ex*CB.p1shot[1]+ey*CB.p1shot[2])/l; if not bs or s&gt;bs then b,bs=e,s end end
    if b and bs&gt;0.9 then tgt,td=b,b.d2 end
  end
  local threat,thd,nearShot,nsd
  for _,p in ipairs(r.shots) do
    local rx,ry=mx-p.x,my-p.y; local d2=rx*rx+ry*ry
    if d2&lt;P.melee_shot_range^2 and (not nsd or d2&lt;nsd) then nearShot,nsd=p,d2 end
    if d2&lt;P.dodge_range^2 then local sp=math.sqrt(p.vx*p.vx+p.vy*p.vy)
      if sp&gt;0.3 then local ux,uy=p.vx/sp,p.vy/sp; local along=rx*ux+ry*uy
        if along&gt;0 then local qx,qy=rx-along*ux,ry-along*uy; local perp=math.sqrt(qx*qx+qy*qy)
          if perp&lt;P.dodge_line and (not thd or d2&lt;thd) then threat,thd=p,d2; p.px,p.py,p.perp=qx,qy,perp end end end end
  end
  local function hazNear(x,y,rad) for _,h in ipairs(r.haz) do if (h.x-x)^2+(h.y-y)^2&lt;rad*rad then return h end end end
  local mtgt,mtd
  if melee then for _,e in ipairs(r.enemies) do local d=(e.x-mx)^2+(e.y-my)^2; if not mtd or d&lt;mtd then mtgt,mtd=e,d end end end
  local carT
  if not melee and frac&gt;P.ammo_careful then for _,h in ipairs(r.haz) do if h.n=="Car" or (P.shoot_barrels and h.n:find("Barrel")) then local d=(h.x-mx)^2+(h.y-my)^2
    if d&gt;P.car_safe^2 and (h.x-px)^2+(h.y-py)^2&gt;P.car_safe_p1^2 and inRange(h.x,h.y) and los(W,mx,my,h.x,h.y) then
      local n=0 for _,e in ipairs(r.enemies) do if (e.x-h.x)^2+(e.y-h.y)^2&lt;P.car_enemy_radius^2 then n=n+1 end end
      if n&gt;=P.car_enemies then carT={c=h.c,x=h.x,y=h.y}; break end end end end end
  local low=hp&lt;=math.max(P.low_hp_min,mhp*P.low_hp_frac)
  if low and not CB.lowMode then CB.lowMode=(math.random()&lt;P.low_careful_chance) and "careful" or "fight"; CB.hpGo={} end
  if CB.headless then CB.lowMode=nil end
  if CB.lowMode and hp&gt;=mhp*P.low_hp_recover then CB.lowMode=nil end
  local careful=CB.lowMode=="careful"
  local coward=careful or (not melee and frac&lt;P.ammo_coward)
  if CB.btnOff and T&gt;CB.btnOff then buttons(0); CB.btnOff=nil end
  local lootGoal=WM({hp=hp,mhp=mhp,P=P,T=T,me=me,r=r,W=W,mx=mx,my=my,px=px,py=py,wep=wep,visible=visible,threat=threat,careful=careful,tgt=tgt,td=td})
  local resGoal=(not lootGoal) and RS({P=P,T=T,me=me,r=r,mx=mx,my=my,px=px,py=py,wep=wep,hp=hp,mhp=mhp,visible=visible,threat=threat}) or nil
  local vx,vy=0,0
  local mode="follow"
  CB.meleeBlocked=false
  -- 1) dodge
  if threat and not CB.headless and not (melee and nearShot) then
    if threat.c~=CB.thC then CB.thC=threat.c; CB.thReact=T+P.dodge_react_min+math.random()*P.dodge_react_rand; CB.thIgnore=math.random()&lt;P.dodge_miss end
    if T&gt;=CB.thReact and not CB.thIgnore then
      local pl=threat.perp; local nx,ny
      if pl&lt;0.5 then local s=(math.random()&lt;0.5) and 1 or -1; local sp=math.sqrt(threat.vx^2+threat.vy^2); nx,ny=-threat.vy/sp*s,threat.vx/sp*s else nx,ny=threat.px/pl,threat.py/pl end
      local ad=math.sqrt(thd)+0.01; local ax,ay=(mx-threat.x)/ad,(my-threat.y)/ad
      if CB.char=="Fish" then CB.dodgeV={nx,ny}; if thd&lt;P.fish_roll_range^2 and T&gt;(CB.rollT or 0) then CB.rollT=T+P.fish_roll_cd; trig(255,nil); CB.rollOff=T+0.15 end
      else local dx,dy=nx*P.dodge_perp+ax*(1-P.dodge_perp),ny*P.dodge_perp+ay*(1-P.dodge_perp); local l=math.sqrt(dx*dx+dy*dy)+0.001; CB.dodgeV={dx/l,dy/l} end
      CB.dodgeUntil=T+P.dodge_time
    end
  end
  if CB.dodgeUntil and T&lt;CB.dodgeUntil then vx,vy=CB.dodgeV[1]*P.dodge_speed,CB.dodgeV[2]*P.dodge_speed; mode="dodge" end
  if CB.headless and mode=="follow" then
    local hb,hbd for _,h in ipairs(r.hps) do local d=(h.x-mx)^2+(h.y-my)^2; if d&lt;300*300 and los(W,mx,my,h.x,h.y) and (not hbd or d&lt;hbd) then hb,hbd=h,d end end
    if hb then local ux,uy=steerTo(r,P,T,mx,my,hb.x,hb.y); vx,vy=ux*1.3,uy*1.3; mode="headless-hp"
    elseif tgt then local ex,ey=tgt.x-mx,tgt.y-my; local ed=math.sqrt(td)+0.01; if ed&gt;(melee and 24 or 60) then vx,vy=ex/ed*1.3,ey/ed*1.3 end; mode="berserk" end
  end
  -- 2) low HP: health first, cover only when crowded, otherwise keep following
  if mode=="follow" and coward then
    local best,bd
    for _,h in ipairs(careful and r.hps or {}) do local d=(h.x-mx)^2+(h.y-my)^2
      if d&lt;P.hp_seek_range^2 and los(W,mx,my,h.x,h.y) then
        if CB.hpGo[h.c]==nil then CB.hpGo[h.c]=math.random()&lt;(melee and P.hp_go_melee or P.hp_go_gun) end
        if CB.hpGo[h.c] and (not bd or d&lt;bd) then best,bd=h,d end end end
    if best then local d=math.sqrt(bd)+0.01; local ux,uy=steerTo(r,P,T,mx,my,best.x,best.y); vx,vy=ux*1.2,uy*1.2; mode="health"
    elseif visible&gt;P.low_open_max_enemies then
      if T&gt;(CB.coverT or 0) then CB.coverT=T+0.5; local bp,bs
        for _,rad in ipairs({0,32,56,80}) do for k=0,(rad==0 and 0 or 11) do
          local a=k*math.pi/6; local cx,cy=mx+math.cos(a)*rad,my+math.sin(a)*rad
          if not W[(math.floor(cx/16)+20000)*100000+math.floor(cy/16)+20000] and (rad==0 or los(W,mx,my,cx,cy)) then
            local seen=0 for _,e in ipairs(r.enemies) do if (e.x-cx)^2+(e.y-cy)^2&lt;P.range_r^2 and los(W,e.x,e.y,cx,cy) then seen=seen+1 end end
            local sc=seen*1000+rad*0.5+math.sqrt((cx-px)^2+(cy-py)^2)
            if not bs or sc&lt;bs then bp,bs={cx,cy},sc end end end end
        CB.cover=bp end
      if CB.cover then local dx,dy=CB.cover[1]-mx,CB.cover[2]-my; local d=math.sqrt(dx*dx+dy*dy); if d&gt;6 then vx,vy=steerTo(r,P,T,mx,my,CB.cover[1],CB.cover[2]) end end
      mode="cover"
    end
  end
  -- peek-shooting from corners
  do
    local sn=0 for _,s in ipairs(r.shots) do if (s.x-mx)^2+(s.y-my)^2&lt;120*120 then sn=sn+1 end end
    local danger=sn&gt;=P.peek_shots or hp&lt;mhp*0.6
    if not melee and tgt and not CB.headless and not CB.peek and danger and (mode=="follow" or mode=="cover") and CB.peekTried~=tgt.c then
      CB.peekTried=tgt.c
      if math.random()&lt;P.peek_chance then local pp=findPeek(r,W,mx,my,tgt.x,tgt.y,px,py)
        if pp then pp.phase="hide"; pp.t=T+P.peek_hide*(0.7+math.random()*0.6); pp.tc=tgt.c; pp.tx,pp.ty=tgt.x,tgt.y; pp.alive=T; pp.start=T; CB.peek=pp end end
    end
    local pk=CB.peek
    if pk then
      for _,e in ipairs(r.enemies) do if e.c==pk.tc then pk.tx,pk.ty=e.x,e.y; pk.alive=T end end
      if danger then pk.calmT=nil else pk.calmT=pk.calmT or T end
      if T-pk.alive&gt;1.5 or T-pk.start&gt;P.peek_max_time or (pk.calmT and T-pk.calmT&gt;3) or melee then CB.peek=nil
      elseif mode=="follow" or mode=="cover" then
        if T&gt;pk.t then if pk.phase=="hide" then pk.phase="out"; pk.t=T+P.peek_out*(0.7+math.random()*0.6) else pk.phase="hide"; pk.t=T+P.peek_hide*(0.7+math.random()*0.6) end end
        local gx,gy=(pk.phase=="hide") and pk.hx or pk.ox,(pk.phase=="hide") and pk.hy or pk.oy
        local dx,dy=gx-mx,gy-my; local d=math.sqrt(dx*dx+dy*dy)
        if d&gt;2 then vx,vy=dx/d,dy/d else vx,vy=0,0 end
        mode="peek-"..pk.phase
      end
    end
  end
  if mode=="follow" and lootGoal then local dx,dy=lootGoal[1]-mx,lootGoal[2]-my; local d=math.sqrt(dx*dx+dy*dy)+0.01; if d&gt;2 then local f=d&gt;12 and 1 or 0.4; local ux,uy=dx/d,dy/d; if d&gt;12 then ux,uy=steerTo(r,P,T,mx,my,lootGoal[1],lootGoal[2]) end; vx,vy=ux*f,uy*f end; mode="loot" end
  if mode=="follow" and resGoal then local ux,uy=steerTo(r,P,T,mx,my,resGoal[1],resGoal[2]); vx,vy=ux,uy; mode="resource" end
  -- 3) combat movement
  if mode=="follow" and tgt then
    local ex,ey=tgt.x-mx,tgt.y-my; local ed=math.sqrt(td)+0.01
    if melee and not careful then
      if T&lt;(CB.backUntil or 0) then vx,vy=-ex/ed,-ey/ed; mode="melee-back"
      elseif ed&gt;P.melee_stop and ed&lt;160 then local n=0 for _,o in ipairs(r.enemies) do if (o.x-tgt.x)^2+(o.y-tgt.y)^2&lt;80*80 then n=n+1 end end; if n&lt;=P.melee_crowd_max then vx,vy=ex/ed*1.2,ey/ed*1.2; mode="melee-in" else CB.meleeBlocked=true end end
    elseif not melee and frac&lt;=P.ammo_careful and frac&gt;P.ammo_desperate and ed&gt;P.careful_close_to and not careful and visible&lt;=2 then vx,vy=ex/ed,ey/ed; mode="close-in"
    end
  end
  if mode=="follow" and close and not CB.headless and (not melee or CB.meleeBlocked) then local ex,ey=mx-close.x,my-close.y; local ed=math.sqrt(cd)+0.01; vx,vy=vx+ex/ed*1.1,vy+ey/ed*1.1 end
  if mode=="follow" then
    local off=(CB.fmode=="behind") and -P.behind_off or ((CB.fmode=="ahead") and P.ahead_off or 0)
    if coward then off=-P.behind_off end
    local axp,ayp=px+tdx*off,py+tdy*off
    if not solo and p1 then local pid=readInteger(p1+0xBC); for _,s in ipairs(r.pshots) do if s.cr==pid then local l=math.sqrt(s.vx^2+s.vy^2); if l&gt;0.5 then CB.p1shot={s.vx/l,s.vy/l,T} end break end end end
    if visible==0 and not coward and CB.p1shot and T-CB.p1shot[3]&lt;P.shotdir_time then axp,ayp=px+CB.p1shot[1]*P.shotdir_off,py+CB.p1shot[2]*P.shotdir_off; CB.goingShot=true else CB.goingShot=false end
    local dx,dy=axp-mx,ayp-my; local d=math.sqrt(dx*dx+dy*dy)+0.01
    local pd=math.sqrt((px-mx)^2+(py-my)^2)
    if d&gt;P.follow_slack or pd&gt;P.follow_max then local f=(pd&gt;P.sprint_dist) and 1.3 or 1; local ux,uy=steerTo(r,P,T,mx,my,axp,ayp); vx,vy=vx+ux*f,vy+uy*f end
    if tgt and d&lt;=P.follow_slack then
      if T&gt;(CB.strafeT or 0) then CB.strafeT=T+0.8+math.random()*1.4; CB.strafe=(math.random()&lt;0.5) and -1 or 1; CB.pause=math.random()&lt;P.strafe_pause end
      if not CB.pause then local ex,ey=tgt.x-mx,tgt.y-my; local ed=math.sqrt(td)+0.01; vx,vy=vx-ey/ed*P.strafe*CB.strafe,vy+ex/ed*P.strafe*CB.strafe end
    end
  end
  if mode~="dodge" and not CB.headless then local ce,cd2 for _,e in ipairs(r.enemies) do local d=(e.x-mx)^2+(e.y-my)^2; if not cd2 or d&lt;cd2 then ce,cd2=e,d end end
    if ce and cd2&lt;P.contact_avoid^2 then local d=math.sqrt(cd2)+0.01; vx,vy=vx+(mx-ce.x)/d*1.5,vy+(my-ce.y)/d*1.5; if mode=="follow" then mode="contact" end end end
  CB.fzOut=nil
  if (mode=="follow" or mode=="cover") and not (CB.dodgeUntil and T&lt;CB.dodgeUntil) then
    local o=FZ({hp=hp,mhp=mhp,P=P,T=T,r=r,mx=mx,my=my,px=px,py=py,solo=solo,visible=visible,tgt=tgt,threat=threat,coward=coward,wep=wep,frac=frac})
    if o then CB.fzOut=o; if o.move then vx,vy=o.vx,o.vy; mode="fz:"..o.k end end
  elseif CB.fz and CB.fz.k~="hide" then CB.fz=nil end
  local moved=((mx-(CB.lx or mx))^2+(my-(CB.ly or my))^2)
  if (vx~=0 or vy~=0) and moved&lt;0.02 then CB.stuck=(CB.stuck or 0)+1 else CB.stuck=0 end
  if CB.stuck&gt;10 then CB.wig=25; CB.wigs=(math.random()&lt;0.5) and -1 or 1; CB.stuck=0 end
  if (CB.wig or 0)&gt;0 then CB.wig=CB.wig-1; vx,vy=-vy*CB.wigs+vx*0.3,vx*CB.wigs+vy*0.3 end
  CB.lx,CB.ly=mx,my
  stick(8,vx,vy,(vx==0 and vy==0) and 0 or 30000)
  do local l=math.sqrt(vx*vx+vy*vy); if l&gt;0.01 then CB.cmdX,CB.cmdY=vx/l,vy/l else CB.cmdX,CB.cmdY=0,0 end end
  CB.mode=mode
  -- aiming / firing
  local shootAt=nil
  if melee then
    if nearShot then shootAt={x=nearShot.x,y=nearShot.y,c=nearShot.c,d=math.sqrt(nsd),swing=true}
    elseif mtgt and not careful and math.sqrt(mtd)&lt;P.melee_swing_range then shootAt={x=mtgt.x,y=mtgt.y,c=mtgt.c,d=math.sqrt(mtd),swing=true}
    elseif tgt then shootAt={x=tgt.x,y=tgt.y,c=tgt.c,d=math.sqrt(td),swing=false} end
  elseif carT then shootAt={x=carT.x,y=carT.y,c=carT.c,d=math.sqrt((carT.x-mx)^2+(carT.y-my)^2),swing=true}
  elseif tgt then
    local ed=math.sqrt(td)
    local allow=true
    if CB.headless then allow=true
    elseif mode=="cover" then allow=ed&lt;P.low_threat_range
    elseif frac&lt;=P.ammo_desperate then allow=ed&lt;P.desperate_range end
    if EXPLO[wep] and not CB.openOK then allow=false end
    shootAt={x=tgt.x,y=tgt.y,c=tgt.c,d=ed,swing=allow}
  end
  local fo=CB.fzOut
  if fo then
    if fo.noShoot then shootAt=nil end
    if fo.aim then shootAt={x=fo.aim.x,y=fo.aim.y,c="fz"..fo.k,d=math.sqrt((fo.aim.x-mx)^2+(fo.aim.y-my)^2)+0.01,swing=fo.fireNormal or false} end
  end
  local ov=(CB.tele and T&lt;CB.tele.untilT and CB.tele) or (CB.strikeAim and T&lt;CB.strikeAim.untilT and CB.strikeAim)
  if ov then shootAt={x=ov.x,y=ov.y,c="ov",d=math.sqrt((ov.x-mx)^2+(ov.y-my)^2)+0.01,swing=false} end
  local wantX,wantY=0,0
  if shootAt then
    if shootAt.c~=CB.tc then CB.tc=shootAt.c; CB.react=T+(melee and P.melee_react_min or P.react_min)+math.random()*(melee and P.melee_react_rand or P.react_rand) end
    local ex,ey=shootAt.x-mx,shootAt.y-my; local ed=shootAt.d+0.01
    local m=math.max(0.35,math.min(1,ed/220)); wantX,wantY=ex/ed*m,ey/ed*m
  else CB.tc=nil
    if vx~=0 or vy~=0 then local vd=math.sqrt(vx*vx+vy*vy); wantX,wantY=vx/vd*0.3,vy/vd*0.3 end
  end
  local k=shootAt and (melee and P.melee_aim_smooth or P.aim_smooth) or P.aim_idle_smooth
  CB.ax=(CB.ax or 0)+(wantX-(CB.ax or 0))*k; CB.ay=(CB.ay or 0)+(wantY-(CB.ay or 0))*k
  local am=math.sqrt(CB.ax^2+CB.ay^2)
  if am&gt;0.02 then stick(0x0C,CB.ax,CB.ay,am*30000) else stick(0x0C,0,0,0) end
  local fire=false
  if shootAt and shootAt.swing and am&gt;0.05 and T&gt;=CB.react then
    local ex,ey=shootAt.x-mx,shootAt.y-my
    local aligned=(CB.ax*ex+CB.ay*ey)/(am*shootAt.d+0.01)&gt;(melee and 0.9 or P.aim_align)
    if aligned then
      if melee then
        if T&gt;(CB.swingT or 0) then CB.swingT=T+P.melee_cooldown; fire=true; if not nearShot then CB.backUntil=T+P.melee_back_time end end
      elseif frac&lt;=P.ammo_careful and not CB.headless then
        if T&gt;(CB.burstPause or 0) then CB.fire=not CB.fire; fire=CB.fire
          if fire then CB.burstN=(CB.burstN or 0)+1; if CB.burstN&gt;=(CB.burstMax or 3) then CB.burstN=0; CB.burstMax=P.burst_min+math.random(0,P.burst_rand); CB.burstPause=T+P.burst_pause+math.random()*P.burst_pause_rand end end end
      else CB.fire=not CB.fire; fire=CB.fire end
    end
  end
  if fo and fo.fireBit~=nil then fire=fo.fireBit and am&gt;0.1 end
  if fire and melee and not P.reckless and hazNear(mx,my,P.melee_haz_radius) then fire=false end
  if fire and not melee and shootAt then for _,h in ipairs(r.haz) do if h.n=="CarVenus" or (not P.reckless and (h.x-mx)^2+(h.y-my)^2&lt;P.haz_self_safe^2) then
    local ax,ay=shootAt.x-mx,shootAt.y-my; local L2=ax*ax+ay*ay+0.01; local t=((h.x-mx)*ax+(h.y-my)*ay)/L2
    if t&gt;0 and t&lt;1.3 then local qx,qy=mx+ax*t-h.x,my+ay*t-h.y; if qx*qx+qy*qy&lt;P.venus_clear^2 then fire=false end end end end end
  -- ===== character specials (left trigger) =====
  local ch=CB.char; local wantLT=false
  local function pulse(cd) CB.ltUntil=T+0.12; CB.spCD=T+cd end
  local shotsNear=0 for _,s in ipairs(r.shots) do if (s.x-mx)^2+(s.y-my)^2&lt;P.sp_shot_radius^2 then shotsNear=shotsNear+1 end end
  local bwep=CB.bwep or 0
  local tb=hasSkill(5)
  local function aimedAt(o) if not o then return false end local ex,ey=o.x-mx,o.y-my; local d=math.sqrt(ex*ex+ey*ey)+0.01; return am&gt;0.05 and (CB.ax*ex+CB.ay*ey)/(am*d)&gt;0.97 end
  local function safeSpot()
    if CB.cover then return CB.cover[1],CB.cover[2] end
    local sx,sy,n=0,0,0 for _,e in ipairs(r.enemies) do if (e.x-mx)^2+(e.y-my)^2&lt;200*200 then sx,sy,n=sx+e.x,sy+e.y,n+1 end end
    if n&gt;0 then local dx,dy=mx-sx/n,my-sy/n; local l=math.sqrt(dx*dx+dy*dy)+0.01; return mx+dx/l*P.crystal_tp_dist,my+dy/l*P.crystal_tp_dist end
    return px,py end
  if ch=="Crystal" and tb then
    if CB.tpHold then
      local jumped=(mx-CB.tpHold.x0)^2+(my-CB.tpHold.y0)^2&gt;24*24
      if jumped or T-CB.tpHold.t&gt;P.crystal_tb_maxhold then CB.tpHold=nil; CB.tele=nil; CB.spCD=T+P.crystal_tp_cd
      else wantLT=true; if CB.tele then CB.tele.untilT=T+0.2 end end
    elseif CB.tele and T&lt;CB.tele.untilT then
      if aimedAt(CB.tele) then CB.tpHold={t=T,x0=mx,y0=my}; CB.tele.untilT=T+0.2; wantLT=true end
    elseif T&gt;(CB.spCD or 0) then
      local crowd=0 for _,e in ipairs(r.enemies) do if (e.x-mx)^2+(e.y-my)^2&lt;P.crystal_tp_crowd_r^2 then crowd=crowd+1 end end
      local heavy=shotsNear&gt;=P.crystal_shots or (threat and thd&lt;25*25 and shotsNear&gt;=2)
      local far=(not solo) and p1 and ((px-mx)^2+(py-my)^2&gt;P.crystal_tp_far^2) and not los(W,mx,my,px,py)
      if heavy or crowd&gt;=P.crystal_tp_crowd_n then local x,y=safeSpot(); CB.tele={x=x,y=y,untilT=T+0.5}
      elseif far then CB.tele={x=px,y=py,untilT=T+0.5} end
    end
    if wantLT then fire=false end
  elseif ch=="Crystal" then
    if shotsNear&gt;=P.crystal_shots or (threat and thd&lt;25*25 and shotsNear&gt;=2) then CB.spUntil=math.max(CB.spUntil or 0,T+P.crystal_hold) end
    wantLT=T&lt;(CB.spUntil or 0); if wantLT then fire=false end
  elseif ch=="Eyes" then
    if threat and T&gt;(CB.eyesNext or 0) then CB.eyesNext=T+1.0; if math.random()&lt;P.eyes_chance then CB.spUntil=T+P.eyes_min+math.random()*P.eyes_rand end end
    wantLT=T&lt;(CB.spUntil or 0)
  elseif ch=="Melting" then
    if visible&gt;0 and r.names.Corpse and T&gt;(CB.spCD or 0) then pulse(P.melting_cd) end
  elseif ch=="Plant" then
    if tgt and td&lt;P.plant_range^2 and am&gt;0.3 and T&gt;(CB.spCD or 0) then pulse(P.plant_cd) end
  elseif ch=="Steroids" then
    if fire and bwep~=0 and (MELEE[bwep] or ammoFracG(me,bwep)&gt;P.ammo_desperate) then wantLT=true end
  elseif ch=="Y.V." then
    local okUse=frac&gt;P.ammo_careful
    if tb then okUse=frac&gt;P.yv_tb_frac and (visible&gt;=P.yv_tb_enemies or (tgt and td&lt;60*60)) end
    if fire and not melee and okUse and not (fo and fo.fireBit~=nil) then wantLT=true; fire=false end
  elseif ch=="Robot" then
    if CB.foodEat and T&gt;CB.foodEat then CB.foodEat=nil; pulse(P.robot_cd)
    elseif CB.eatPlan then if T&gt;CB.eatPlan.t then pulse(P.robot_cd); CB.eatPlan=nil end
    elseif bwep~=0 and T&gt;(CB.spCD or 0) and not CB.loot then
      local function val(id,other) local s=CB.keepScore(id,other); if not MELEE[id] and ammoFracG(me,id)&lt;P.ammo_desperate then s=s-P.empty_penalty end return s end
      local vw,vb=val(wep,bwep),val(bwep,wep)
      local worseIsB=vb&lt;vw
      local worse=worseIsB and bwep or wep
      local lastHP=tb and P.robot_tb_last_hp or P.robot_last_hp
      local lastResort=(hp&lt;=math.max(1,mhp*lastHP) and #r.hps==0) or (not MELEE[wep] and not MELEE[bwep] and ammoFracG(me,wep)&lt;P.ammo_desperate and ammoFracG(me,bwep)&lt;P.ammo_desperate)
      local spare=false for _,w in ipairs(r.weps) do if (w.x-mx)^2+(w.y-my)^2&lt;P.robot_spare_range^2 and los(W,mx,my,w.x,w.y) then spare=true break end end
      if lastResort and spare and not FAV[worse] then
        if worseIsB then buttons(0x8000); CB.btnOff=T+0.12; CB.eatPlan={t=T+0.45}; CB.spCD=T+1 else pulse(P.robot_cd) end
      end
    end
  elseif ch=="Rebel" then
    if hp&gt;=mhp*P.rebel_hp and visible&gt;=P.rebel_enemies and T&gt;(CB.spCD or 0) then pulse(P.rebel_cd) end
  elseif ch=="Horror" then
    wantLT=visible&gt;=P.horror_enemies and frac&lt;P.ammo_careful and hp&lt;=mhp*P.horror_hp
    if wantLT then fire=false end
  elseif ch=="Rogue" then
    local sv=NT.var(me,NT.KEYS.strikes); local strikes=sv and readDouble(sv) or 0
    if CB.strikeAim and T&lt;CB.strikeAim.untilT then
      if aimedAt(CB.strikeAim) then pulse(P.rogue_cd); CB.strikeAim=nil end
    elseif strikes&gt;0 and T&gt;(CB.spCD or 0) then
      local best,bv,bn
      for _,e in ipairs(r.enemies) do
        local safe=(e.x-mx)^2+(e.y-my)^2&gt;P.strike_safe^2 and (solo or (e.x-px)^2+(e.y-py)^2&gt;P.strike_safe^2)
        if safe and inRange(e.x,e.y) then local n,v=0,0
          if ROGUE_BIG[e.n] then v=v+1000 end
          for _,o in ipairs(r.enemies) do if (o.x-e.x)^2+(o.y-e.y)^2&lt;60*60 then n=n+1; local mv=NT.var(o.c,NT.KEYS.maxhp); v=v+(mv and readDouble(mv) or 1) end end
          if not bv or v&gt;bv then best,bv,bn=e,v,n end end end
      if best then local seen={} for _,o in ipairs(r.enemies) do seen[o.n]=true end; for n in pairs(seen) do if not CB.enemyNames then CB.enemyNames={} end CB.enemyNames[n]=true end end
      if best and (bn&gt;=P.rogue_cluster or bv&gt;=1000 or bv&gt;=P.rogue_hp_value) then CB.strikeAim={x=best.x,y=best.y,untilT=T+0.6} end
    end
  end
  if ch~="Fish" and ch~="Chicken" then wantLT=wantLT or T&lt;(CB.ltUntil or 0); if fo and fo.fireBit~=nil then wantLT=false end; trig(wantLT and 255 or 0,nil) end
  CB.special=wantLT and ch or nil
  trig(nil,fire and 255 or 0)
  CB.nE=#r.enemies; CB.vis=visible; CB.tgt=tgt and tgt.n
end
local ENV={Wall=1,Floor=1,FloorExplo=1,TopSmall=1,TopDecal=1,Bones=1,Detail=1,Dust=1,Smoke=1,Debris=1,WindNight=1,Scorch=1,ScorchTop=1,Shell=1,BulletHit=1,SnowFlake=1,SnowFloor=1}
local function alive()
  local pid=getOpenedProcessID()
  local base=pid and pid~=0 and getAddressSafe("nuclearthrone.exe")
  if base and readBytes(base,1) then return true end
  local np=getProcessIDFromProcessName("nuclearthrone.exe")
  if np and np~=0 then openProcess(np); CB.pid=nil; CB.PS=nil; CB.anchor=nil; CB.log[#CB.log+1]=string.format("%.1f reattached %d",now(),np) end
  return false
end
local function tick()
  CB.ticks=CB.ticks+1
  if now()&lt;(CB.backoff or 0) then return end
  if not alive() then CB.backoff=now()+2; CB.q={}; CB.state="gone"; return end
  if not ensurePad() then CB.backoff=now()+2; return end
  local dn=isKeyPressed(VK_LBUTTON)
  if dn and not CB.gdown then local mx,my=getMousePos(); CB.log[#CB.log+1]=string.format("%.1f CLICK at %d,%d state=%s",now(),mx,my,tostring(CB.state)) end
  CB.gdown=dn
  local r=scan()
  if not r then neutral(); CB.q={}; CB.state="menu?"; return end
  local st=(#r.players&gt;0) and "game" or ((#r.chars&gt;0) and "lobby" or "menu")
  -- screen fingerprint (sampled once per second)
  if now()-(CB.sigT or 0)&gt;1 then CB.sigT=now()
    local t={} for n,_ in pairs(r.names) do if not ENV[n] then t[#t+1]=n end end table.sort(t)
    local sig=table.concat(t,",")
    if sig~=CB.sig then CB.sig=sig; CB.log[#CB.log+1]=string.format("%.1f SCREEN[%s] %s",now(),st,sig) end
  end
  if st~=CB.state then
    if #CB.q&gt;0 then CB.q={}; CB.qT=nil; CB.needPk=nil; CB.log[#CB.log+1]=string.format("%.1f queue aborted (%s-&gt;%s)",now(),tostring(CB.state),st) end
    neutral()
    if st=="lobby" then if CB.personaChoice=="random" then CB.applyPersona() end; CB.solo=false; CB.botDead=false; CB.lastN=nil; CB.joined=false; CB.scr=nil; CB.rebelFav=nil; CB.triedGold={}; CB.ignoreW={}; CB.loot=nil; CB.regret=nil; CB.lootGoal=nil end
    if st=="game" then CB.p1pick=nil end
    if st~="game" then CB.me=nil; CB.greeted=false end
    CB.log[#CB.log+1]=string.format("%.1f state %s",now(),st)
    CB.state=st
  end
  if st=="menu" then return end
  keepPolled()
  if runQueue() then return end
  if st=="game" and (r.names.LevCont or r.names.SkillIcon or r.names.SpiralCont) then neutral(); CB.mode="between levels"; return end
  if st=="lobby" then lobby(r) elseif st=="game" then game(r) end
end
CB.tick=tick
CB.timer=createTimer(nil,false); CB.timer.Interval=30
CB.timer.OnTimer=function() local ok,e=pcall(tick); if not ok then if CB.err~=e then CB.log[#CB.log+1]="ERROR "..tostring(e) end; CB.err=e; if not CB.errSaid then CB.errSaid=true; pcall(speak,"Something broke in my code.",false) end end end
CB.timer.Enabled=true
if CB.hk then pcall(function() CB.hk.destroy() end) end
CB.hk=createHotkey(function() pcall(CB.cyclePersona) end, VK_CONTROL, VK_F5)


{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.timer then CB.timer.destroy() CB.timer=nil end
if CB and CB.hk then pcall(function() CB.hk.destroy() end) CB.hk=nil end
if CB and CB.neutral then pcall(CB.neutral) end
{$asm}
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>124</ID>
      <Description>"Radar window"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if NT.radar then pcall(function() NT.radar.timer.destroy() NT.radar.form.destroy() end) end
local R={size=220, range=495, zoomRanges={495,250}, zi=1, names={}}
NT.radar=R
local f=createForm(false)
f.Caption="NT radar"; f.BorderStyle=bsNone; f.Width=R.size; f.Height=R.size; f.FormStyle=fsSystemStayOnTop
pcall(function() f.AlphaBlend=true; f.AlphaBlendValue=200 end)
f.Left=40; f.Top=40
local img=createImage(f); img.Align=alClient
img.Picture.Bitmap.Width=R.size; img.Picture.Bitmap.Height=R.size
R.form=f; R.img=img
img.OnMouseDown=function(sender,button,x,y)
  if button==mbLeft then local mx,my=getMousePos(); R.drag={mx,my,f.Left,f.Top}
  elseif button==mbRight then R.zi=(R.zi % #R.zoomRanges)+1; R.range=R.zoomRanges[R.zi] end
end
img.OnMouseMove=function() if R.drag then local mx,my=getMousePos(); f.Left=R.drag[3]+mx-R.drag[1]; f.Top=R.drag[4]+my-R.drag[2] end end
img.OnMouseUp=function() R.drag=nil end
R.SWP=getAddress("user32.SetWindowPos",true)
R.SWL=getAddress("user32.SetWindowLongPtrA",true)
R.GWL=getAddress("user32.GetWindowLongPtrA",true)
function R.detach() pcall(function()
  executeCodeLocalEx(R.SWL, f.Handle, -8, 0)
  local ex=executeCodeLocalEx(R.GWL, f.Handle, -20)
  executeCodeLocalEx(R.SWL, f.Handle, -20, (ex | 0x80 | 0x8))
end) end
function R.topmost() pcall(function() executeCodeLocalEx(R.SWP, f.Handle, -1, 0, 0, 0, 0, 0x13) end) end
R.detach()
R.ticks=0
local FLOOR={Floor=1,FloorExplo=1,SnowFloor=1}
local PROPS={Hydrant=1,StreetLight=1,Car=1,Barrel=1,ToxicBarrel=1,GoldBarrel=1,Cactus=1,BigSkull=1,Tires=1,MoneyPile=1,Bush=1}
local function nameOf(inst)
  local o=readQword(inst+0x90); if not o or o&lt;0x10000 then return nil end
  local n=R.names[o]
  if n==nil then local s=readQword(o); n=(s and s&gt;0x10000) and (readString(s,32) or false) or false; R.names[o]=n end
  return n or nil
end
local function draw()
  pcall(NT.tick)
  local pl=NT.cache.Player
  local bmp=img.Picture.Bitmap; local cv=bmp.Canvas
  local S=R.size; local scale=S/(2*R.range)
  cv.Brush.Color=0x101010; cv.fillRect(0,0,S,S)
  if not pl then cv.Font.Color=0xFFFFFF; cv.textOut(8,8,"no Player"); img.repaint(); return end
  local px,py=readFloat(pl+0xF4),readFloat(pl+0xF8)
  local h=pl; local k=0
  while k&lt;20000 do local p=readQword(h+0x1A8); if not p or p==0 then break end h=p k=k+1 end
  local walls,floors,things={}, {}, {}
  local c=h; local guard=0
  while c and c~=0 and guard&lt;30000 do
    guard=guard+1
    local x,y=readFloat(c+0xF4),readFloat(c+0xF8)
    if x and math.abs(x-px)&lt;R.range+16 and math.abs(y-py)&lt;R.range+16 then
      local n=nameOf(c)
      if n then
        local sx,sy=(x-px)*scale+S/2,(y-py)*scale+S/2
        if n=="Wall" then walls[#walls+1]={sx,sy}
        elseif FLOOR[n] then floors[#floors+1]={sx,sy}
        elseif n~="Player" then
          local col
          if n=="ChestOpen" then col=nil
          elseif n=="Portal" then col=-2
          elseif n=="HealthChest" then col=-3
          elseif n:find("Chest") then col=0xFF6020
          elseif n:find("Wep") then col=0x40FF40
          elseif n:find("Ammo") then col=0x00E0FF
          elseif n:find("HP") or n:find("Health") then col=-1
          elseif n:find("Pickup") then col=0x40FF40
          elseif PROPS[n] then col=0x907060
          else local rv=NT.var(c,0x19822); if rv and readInteger(rv+12)==0 and readDouble(rv)&gt;0 then col=0x3030FF end end
          if col then things[#things+1]={sx,sy,col,n} end
        end
      end
    end
    c=readQword(c+0x1A0)
  end
  local w=16*scale
  cv.Brush.Color=0x303030; for _,p in ipairs(floors) do cv.fillRect(p[1],p[2],p[1]+w,p[2]+w) end
  cv.Brush.Color=0x8A8A8A; for _,p in ipairs(walls) do cv.fillRect(p[1],p[2],p[1]+w,p[2]+w) end
  for _,t in ipairs(things) do
    if t[3]==-2 then
      cv.Brush.Color=0xD040A0; cv.Pen.Color=0xD040A0; cv.ellipse(t[1]-7,t[2]-7,t[1]+8,t[2]+8)
    elseif t[3]==-3 then
      local x,y=math.floor(t[1]),math.floor(t[2])
      cv.Brush.Color=0xFFFFFF; cv.fillRect(x-6,y-6,x+8,y+8)
      cv.Brush.Color=0x2020E0; cv.fillRect(x-1,y-4,x+3,y+6); cv.fillRect(x-4,y-1,x+6,y+3)
    elseif t[3]==-1 then
      local x,y=math.floor(t[1]),math.floor(t[2])
      cv.Brush.Color=0xFFFFFF; cv.fillRect(x-4,y-4,x+5,y+5)
      cv.Brush.Color=0x2020E0; cv.fillRect(x-1,y-3,x+2,y+4); cv.fillRect(x-3,y-1,x+4,y+2)
    else cv.Brush.Color=t[3]; cv.Pen.Color=t[3]; cv.ellipse(t[1]-3,t[2]-3,t[1]+4,t[2]+4) end
  end
  cv.Brush.Color=0xFFFFFF; cv.Pen.Color=0xFFFFFF; cv.ellipse(S/2-4,S/2-4,S/2+5,S/2+5)
  cv.Pen.Color=0x505050; cv.line(0,0,S-1,0); cv.line(S-1,0,S-1,S-1); cv.line(S-1,S-1,0,S-1); cv.line(0,S-1,0,0)
  img.repaint()
end
R.draw=draw
R.timer=createTimer(nil,false); R.timer.Interval=150
R.timer.OnTimer=function() R.ticks=R.ticks+1; if R.ticks % 13==1 then R.topmost() end; local ok,e=pcall(draw); if not ok then R.err=e end end
R.timer.Enabled=true
f.show()
draw()
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if NT.radar then pcall(function() NT.radar.timer.destroy() end) pcall(function() NT.radar.form.destroy() end) NT.radar=nil end
{$asm}
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>125</ID>
      <Description>"Bot personality: predator"</Description>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>126</ID>
          <Description>"companion"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("companion") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>127</ID>
              <Description>"   Default. Careful, follows, some funzies."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>128</ID>
          <Description>"shadow"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("shadow") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>129</ID>
              <Description>"   Sticks to you, copies your direction and target, few funzies."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>130</ID>
          <Description>"coward"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("coward") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>131</ID>
              <Description>"   Hangs back, hides early, great dodger."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>132</ID>
          <Description>"hunter"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("hunter") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>133</ID>
              <Description>"   Aggressive. Longer range, charges, biggest threats first."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>134</ID>
          <Description>"predator"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("predator") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>135</ID>
              <Description>"   Pure death on legs. No funzies, precise, no wasted ammo."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>136</ID>
          <Description>"spelunker"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("spelunker") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>137</ID>
              <Description>"   Explorer. Wanders further, opens everything, collects plutonium."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>138</ID>
          <Description>"sadist"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("sadist") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>139</ID>
              <Description>"   No safety at all. Cars, barrels, grenades in your face."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>140</ID>
          <Description>"joker"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("joker") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>141</ID>
              <Description>"   Maximum funzies. Explosive props only when you are far."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>142</ID>
          <Description>"random"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if CB and CB.setPersona then CB.setPersona("random") end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>143</ID>
              <Description>"   New personality every run."</Description>
              <GroupHeader>1</GroupHeader>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
  <Comments>MMMM - Marvel Mutant Mutations Mod for Nuclear Throne
Enable the resolver first. Only one mode can be active at a time; the radar works with all of them.
Captain America: when he's down to his fists or out of ammo for his gun, an invisible shield throws incoming fire back at whoever sent it. Some mutations are simply beneath him.
Magneto: your own shots that pass close to your crosshair fall under his control, slowing down and following wherever you point. Even spinning blades obey him and no longer turn on their master.
Jean Grey: enemy fire that strays near your crosshair is seized by her mind, turned to your side and hurled toward wherever you point.
Professor X: takes over the mind of a nearby enemy that shoots. Under his will it grows tougher and fights for you with faster, deadlier shots. The hold breaks if it wanders too far, and the last enemy standing can't be swayed.
Barry Allen: moves faster, reloads faster, and every gun keeps firing as long as the trigger is held.
Juggernaut: enormous health but carries almost no ammo and moves slowly. Starts with heavy tools, reaches further and hits far harder in melee, hurts anything that touches him, and smashes through walls as if they weren't there.
Wonder Woman: carries less ammo than most, but when she crosses her bracelets (crosshair on herself), nearby bullets bounce back at the enemy.
Radar: a small map of the area around you showing walls, enemies, chests, pickups and the portal. Works alongside any mode.
</Comments>
</CheatTable>
