-- Arctic API v1. Read-only overlay; edit these settings, then re-enable the module.
local settings={keys=true,objectives=true,entities=true,hiding_spots=true,sound_warnings=true,distance=true}
local entities={rushmoving='Rush',rushnew='Rush',ambushmoving='Ambush',backdoorrush='Blitz',backdoorlookman='Lookman',eyes='Eyes',screech='Screech',halt='Halt',figurerig='Figure',figure='Figure',seekmoving='Seek',seekrig='Seek',seek='Seek',damseek='Dam Seek',giggleceiling='Giggle',grumblerig='Grumble',queengrumble='Queen Grumble',snare='Snare',dread='Dread',gloombatswarm='Gloombats',a60='A-60',a90='A-90',a120='A-120',haste='Haste',vacuum='Vacuum',dupe='Dupe',fakedoor='Dupe',jeffthekiller='Jeff The Killer',bananapeel='Banana Peel',groundskeeper='Groundskeeper',groundskeeperrig='Groundskeeper',mandrake='Mandrake',surge='Surge',monument='Monument',eyestalk='Eyestalk',bramble='Bramble',worldlotus='World Lotus',seekarm='Seek Arm',seekobstruction='Seek Obstruction'}
local objectives={keyobtain='Key',electricalkeyobtain='Electrical Key',ironkeyobtain='Iron Key',ironkey='Iron Key',skeletonkey='Skeleton Key',timerlever='Timer Lever',leverforgate='Gate Lever',livehintbook='Library Book',livebreakerpolepickup='Breaker',minesgenerator='Generator',minesgatebutton='Gate Button',fuseobtain='Fuse',anchor='Anchor',shears='Shears',lotuspetal='Lotus Petal'}
local hiding={wardrobe='Wardrobe',toolshed='Toolshed',bed='Bed',locker='Locker',closet='Closet'}
local queue,head,found,visible={},1,{},{}
local next_scan=0
local warnings={}
local function normalize(s)
 local out={}
 for i=1,#s do local b=string.byte(s,i);if b>=65 and b<=90 then b=b+32 end;if b>=97 and b<=122 or b>=48 and b<=57 then out[#out+1]=string.char(b) end end
 return table.concat(out)
end
local function scan()
 if head>#queue then
  if arctic.time()<next_scan then return end
  queue={{id=arctic.root(),depth=0}};head=1;found={};visible={};next_scan=arctic.time()+1
 end
 -- Spread scene traversal across updates. Handles survive until the next root().
 for count=1,180 do
  local entry=queue[head];if not entry then break end;head=head+1
  local item=arctic.info(entry.id);local key=normalize(item.name)
  local label,color=entry.label,entry.color
  if settings.entities and entities[key] then label=entities[key];color=0xff7070ff end
  if objectives[key] then local iskey=arctic.contains(key,'key');if iskey and settings.keys or not iskey and settings.objectives then label=objectives[key];color=iskey and 0xffdb70ff or 0x70dfb0ff end end
  if settings.hiding_spots and hiding[key] then label=hiding[key];color=0x78bcffff end
  if settings.sound_warnings and item.class=='Sound' and item.playing then
   local threat=entry.label or entities[key]
   if not threat then for name,title in pairs(entities) do if arctic.contains(key,name) then threat=title;break end end end
   if threat then warnings[threat]=arctic.time()+3 end
  end
  if label and item.position and #found<180 then found[#found+1]={id=entry.id,p=item.position,label=label,color=color} end
  if entry.depth<13 and #queue<7500 then
   -- Skip decorative branches but preserve named threats in the root scene.
   if item.class~='Sound' and item.class~='Script' and item.class~='LocalScript' then
    for _,id in ipairs(arctic.children(entry.id)) do
     if #queue>=7500 then break end
     queue[#queue+1]={id=id,depth=entry.depth+1,label=label,color=color}
    end
   end
  end
 end
 visible=found
end
function on_update()
 scan()
 local me=arctic.players()[1];local origin=me and me.position
 for _,entry in ipairs(visible) do
  local p=arctic.info(entry.id).position or entry.p;local label=entry.label
  if origin and settings.distance then local dx,dy,dz=p.x-origin.x,p.y-origin.y,p.z-origin.z;label=label..' ['..math.floor(math.sqrt(dx*dx+dy*dy+dz*dz))..']' end
  arctic.text(p.x,p.y,p.z,label,entry.color)
 end
 local y=110
 for threat,expires in pairs(warnings) do
  if expires>arctic.time() then arctic.label(24,y,'DOORS: '..threat,0xff7070ff);y=y+22 else warnings[threat]=nil end
 end
 arctic.label(24,y,'DoorsESP | '..#visible..' markers',0xadc8e0ff)
end
