-- Independent renderer. Uses only engine GUI primitives and the game's own -- core debug font by name. No third-party material, texture or font data. return function(sr,C) local World,Gui,V2,V3,Color=sr.World,sr.Gui,sr.Vector2,sr.Vector3,sr.Color local FONT='core/performance_hud/debug' local D={gui=nil,world=nil,ids={},key=nil,mode=nil} local function call(f,...) if type(f)~='function' then return nil end local ok,a,b=pcall(f,...);if ok then return a,b end end local function col(a,c) return Color(math.floor(math.max(0,math.min(1,a))*255),c[1],c[2],c[3]) end local function keep(kind,id) if id~=nil then D.ids[#D.ids+1]={kind,id} end end function D.clear() if D.gui then for _,p in ipairs(D.ids) do call(Gui[p[1]],D.gui,p[2]) end end D.ids={};D.key=nil end local function live(worlds,w) for _,v in pairs(worlds or {}) do if v==w then return true end end return false end function D.reset(worlds) if D.gui and live(worlds,D.world) then D.clear();call(World.destroy_gui,D.world,D.gui) end D.ids={};D.gui=nil;D.world=nil;D.key=nil end function D.ensure(worlds,main) if D.gui and live(worlds,D.world) then return true end D.reset(worlds) -- Same surface choice as DRIVER HUD: a non-main (UI) world, screen GUI. for _,v in ipairs(worlds or {}) do if v~=main then D.world=v;break end end if D.world then D.gui=call(World.create_screen_gui,D.world,'scale',1,1) end return D.gui~=nil end -- Filled rectangle without a material: Stingray's Gui.rect default solid. -- The first failure permanently switches to text-only bars for this run. local function rect(x,y,w,h,a,c,layer) if w<=0 or h<=0 or D.mode=='TEXT' then return false end -- Bottom-up screen coordinates; z of the position is the layer. local ok,id=pcall(Gui.rect,D.gui,V3(x,y,layer or 2),V2(w,h),col(a,c)) if ok and id~=nil then D.mode=D.mode or 'RECT';keep('destroy_rect',id);return true end D.mode='TEXT';return false end local function text(s,x,y,size,a,c) keep('destroy_text',call(Gui.text,D.gui,s,FONT,size,FONT,V2(x,y),col(a,c))) end local WHITE,YELLOW,RED,GREY,DARK={235,240,235},{255,205,60},{255,70,55},{130,130,130},{0,0,0} local function tone(r) if r==nil then return GREY elseif r<=0 then return GREY elseif r<=0.5 then return RED elseif r<=0.75 then return YELLOW end return WHITE end local function ascii(r,n) local k=r and math.floor(r*n+0.5) or 0;return '['..string.rep('#',k)..string.rep('.',n-k)..']' end local function bar(x,y,w,h,r,a,c) if rect(x,y,w,h,a*0.28,DARK,2) then if r and r>0 then rect(x,y,w*math.min(1,r),h,a*0.85,c,3) end local t=math.max(1,h*0.12);rect(x,y,w,t,a*0.5,c,4);rect(x,y+h-t,w,t,a*0.5,c,4) return true end return false end -- Coordinates are Stingray screen space: origin bottom-left, y grows upward. -- C.x/C.y place the panel's top-left corner as a fraction of the screen. function D.draw(w,h,v) local parts={w,h,v.title} for _,r in ipairs(v.rows) do parts[#parts+1]=r.label..(r.hp or '-')..'/'..(r.max or '-') end local key=table.concat(parts,':')..tostring(D.mode) if key==D.key then return end D.clear() local s=math.min(w/1920,h/1080)*C.scale;local a=C.alpha local W=262*s;local H=26*s for _,r in ipairs(v.rows) do H=H+(r.major and 26 or 22)*s end local x=math.max(8*s,math.min(w-W-8*s,w*C.x)) local top=math.max(H+8*s,math.min(h-8*s,h*C.y)) rect(x-6*s,top-H-4*s,W+12*s,H+10*s,a*0.22,DARK,1) text(v.title,x,top-15*s,15*s,a,WHITE) local cy=top-26*s for _,r in ipairs(v.rows) do local rh=(r.major and 26 or 22)*s local ratio=r.hp and r.max and r.max>0 and math.max(0,r.hp)/r.max or nil local c=tone(ratio);local size=(r.minor and 12 or 13)*s local base=cy-rh+6*s text(r.label,x,base,size,a,c) local num=r.hp and (r.hp<=0 and 'X' or tostring(r.hp)) or '--' local bh=(r.major and 12 or 10)*s if not bar(x+112*s,base,95*s,bh,ratio,a,c) then text(ascii(ratio,10),x+112*s,base,size,a,c) end text(num,x+215*s,base,size,a,c) cy=cy-rh end D.key=key end return D end