-- Mech status renderer v1.6: minimal icon + detailed hull bar, bottom-left toward centre, light-grey -- monochrome styled after the stock Helldivers 2 HUD (thin light strokes, -- translucent dark plate, amber only for warnings). Solid Gui.rect only. -- Static layer rebuilt on resolution/config/arm-layout change; dynamic layer on -- value change or while a critical part blinks. Layout is top-down and -- converted to Stingray's bottom-up screen space in put(). return function(sr,C,ART,Fallback) local World,Gui,V2,V3,Color=sr.World,sr.Gui,sr.Vector2,sr.Vector3,sr.Color local D={gui=nil,world=nil,static={},dyn={},skey=nil,dkey=nil,mode=nil,fb=Fallback} 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 dec(s) local t={};if type(s)~='string' then return t end;for a,b,c,d in s:gmatch('(%d+),(%d+),(%d+),(%d+);') do t[#t+1]={tonumber(a),tonumber(b),tonumber(c),tonumber(d)} end;return t end local A={zones={},glyphs={}} for k,z in pairs(ART.zones) do A.zones[k]={fill=dec(z.fill),edge=dec(z.edge),anchor=z.anchor} end A.nfill=dec(ART.neutral.fill);A.nedge=dec(ART.neutral.edge) -- v1.8: per-model arm silhouettes (EXO-45/49/51/55); 'default' otherwise. A.models={} for code,m in pairs(ART.models or {}) do A.models[code]={} for id,z in pairs(m) do A.models[code][id]={fill=dec(z.fill),edge=dec(z.edge),anchor=z.anchor} end end local function zone_art(code,id) local m=A.models[code] or A.models['default'] return (m and m[id]) or A.zones[id] end -- v1.10 HD fonts: pre-rendered per UI scale, anti-aliased (alpha levels). local FS={} local function decset(t) local o={em=t.em,base=t.base,cap=t.cap,lv=t.lv,g={}} for ch,g in pairs(t.g) do local ls={};for i,l in ipairs(g.l) do ls[i]=dec(l) end;o.g[ch]={l=ls,adv=g.adv} end return o end for k,f in pairs(ART.fonts) do FS[tonumber(k)]={big=decset(f.big),small=decset(f.small)} end local F=FS[1] local function pick(s) local best,bd=1,1e9;for k in pairs(FS) do local d=math.abs(k-s);if d0 and zv.hp) then return nil,nil end local r=math.max(0,math.min(1,zv.hp/zv.max));local p=math.floor(r*100+0.5) if p>=100 and zv.hp0 then p=1 end return r,p end ---------------------------------------------------------------- static local function draw_static(g,v) local L=D.static;local s,a=g.s,C.alpha;local x,y=g.x,g.y if C.plate>0 then if not put(L,x-8*s,y-6*s,(PW+16)*s,(g.ph+12)*s,a*C.plate,P.plate,1) then return false end elseif not put(L,x,y,1,1,0,P.plate,1) then return false end text(L,v.title.code,x,y+12*s,12*s,a,P.text,7) text(L,v.title.cn,x+6*s+width(v.title.code,12*s),y+12*s,12*s,a,P.sub,7) -- Explicit approximation marker for spatially inferred ARM association only. -- Pixel-drawn amber ≈: no font change, no claim of a verified native attachment. if v.arm_association=='SPATIAL_HEURISTIC'then local mx=x+3*s for _,dy in ipairs({30,34})do if not put(L,mx,y+dy*s,3*s,s,a,P.warn,8)or not put(L,mx+3*s,y+(dy-1)*s,3*s,s,a,P.warn,8) or not put(L,mx+6*s,y+dy*s,3*s,s,a,P.warn,8)or not put(L,mx+9*s,y+(dy-1)*s,2*s,s,a,P.warn,8)then return false end end end -- hull bar track + 10% ticks local by=y+18*s put(L,x,by,PW*s,7*s,a*0.28,P.faint,3) for i=1,9 do put(L,x+math.floor(PW*i/10)*s,by+(i==5 and 0 or 4)*s,s,(i==5 and 7 or 3)*s,a*0.55,P.plate,12) end -- neutral connectors rects(L,A.nfill,g.sx,g.sy,s,a*0.25,P.struct,4) rects(L,A.nedge,g.sx,g.sy,s,a*0.55,P.faint,5) return true end ---------------------------------------------------------------- dynamic local function draw_dynamic(g,v,blink) local L=D.dyn;local s,a=g.s,C.alpha;local x,y=g.x,g.y local hr=v.hull and v.hull_max and v.hull_max>0 and math.max(0,math.min(v.hull,v.hull_max))/v.hull_max or nil local hc,hk=tone(hr) local hp=hr and math.floor(hr*100+0.5) or nil if hp and hp>=100 and v.hull0 then local bw=math.max(1,math.floor(PW*hr+0.5))*s local ba=(hk=='crit' and blink) and 0.45 or 0.95 put(L,x,by,bw,7*s,a*ba,hk=='ok' and P.ok or hc,9) end for _,id in ipairs(ORDER) do local zv=v.zones[id];local z=zone_art(v.title.code,id) local r,p=pct(zv);local c,k=tone(r) if k=='dead' then -- destroyed: dark fill, bright red outline (blinks slowly) + "损毁" label local on=math.floor((v.clock or 0)*1.2)%2==0 rects(L,z.fill,g.sx,g.sy,s,a*0.7,P.dead,8);rects(L,z.edge,g.sx,g.sy,s,a*(on and 1 or 0.55),P.crit,9) elseif k=='none' then rects(L,z.edge,g.sx,g.sy,s,a*0.45,P.none,9) else local fa=k=='ok' and 0.10 or (k=='crit' and (blink and 0.10 or 0.40) or 0.28) rects(L,z.fill,g.sx,g.sy,s,a*fa,c,8);rects(L,z.edge,g.sx,g.sy,s,a*0.95,k=='ok' and P.ok or c,9) end local cx,cy=g.sx+z.anchor[1]*s,g.sy+z.anchor[2]*s local label=(k=='dead') and '损毁' or (p and (tostring(p)..'%') or '--') local tc=k=='ok' and P.text or (k=='none' and P.none or (k=='dead' and P.crit or c)) stext(L,label,cx,cy,s,a,tc,10) end end ---------------------------------------------------------------- entry local function fbdraw(w,h,v) return D.fb.draw(w,h,{title=v.title.code..(v.arm_association=='SPATIAL_HEURISTIC'and ' [~ARMS]'or ''),rows=v.rows}) end function D.draw(w,h,v) if D.mode=='TEXT' then return fbdraw(w,h,v) end H=h local zones={} for id,zv in pairs(v.zones or {}) do zones[id]=zv end -- arms: map to left/right slots; unknown sides keep numbered labels. v.arms_numbered=false if v.arms then local n=0 for _,a in ipairs(v.arms) do n=n+1 local id=a.side=='L' and 'arm_left' or a.side=='R' and 'arm_right' or (n==1 and 'arm_left' or 'arm_right') if not a.side then v.arms_numbered=true end zones[id]={hp=a.hp,max=a.max} end end v.zones=zones local blink=false for _,zv in pairs(zones) do local r=zv.max and zv.max>0 and zv.hp and zv.hp/zv.max;if r and r>0 and r<=0.25 then blink=(math.floor((v.clock or 0)*2.5)%2==0) end end local skey=table.concat({w,h,C.right,C.bottom,C.scale,C.alpha,C.plate,v.title.code,tostring(v.arms_numbered),tostring(v.arm_association)},':') local parts={tostring(v.hull)};for id,zv in pairs(zones) do parts[#parts+1]=id..'='..tostring(zv.hp)..'/'..tostring(zv.max) end table.sort(parts);local anydead=false;for _,zv in pairs(zones) do if zv.hp and zv.max and zv.max>0 and zv.hp<=0 then anydead=true end end local dkey=skey..table.concat(parts,',')..tostring(blink)..(anydead and tostring(math.floor((v.clock or 0)*1.2)%2) or '') if skey==D.skey and dkey==D.dkey then return end local g=geometry(w,h) if skey~=D.skey then destroy(D.static);destroy(D.dyn);D.static={};D.dyn={};D.dkey=nil if not draw_static(g,v) then destroy(D.static);D.static={};D.mode='TEXT';D.fb.gui=D.gui;D.fb.world=D.world;return fbdraw(w,h,v) end D.mode='MECH';D.skey=skey end destroy(D.dyn);D.dyn={};draw_dynamic(g,v,blink);D.dkey=dkey end return D end