SurfacePaintReview.cs
using Sandbox;
namespace PaintballBaddies;
public sealed class SurfacePaintReview : Component
{
float elapsed;bool done;
protected override void OnUpdate()
{
elapsed+=Time.Delta;if(done||elapsed<2)return;done=true;
var system=PaintImpactSystem.Find(Scene);
int tested=0,hitCount=0;
foreach(var r in Scene.GetAllComponents<ModelRenderer>().ToArray())
{
if(!r.Enabled||!r.GameObject.Active||!r.Model.IsValid()||r is SkinnedModelRenderer||r.GameObject.Tags.Has("paintball_debris")||r.GameObject.Name.Contains("marker",System.StringComparison.OrdinalIgnoreCase))continue;
var bounds=r.Model.Bounds;var center=bounds.Center;bool found=false;
foreach(var dir in new[]{Vector3.Up,Vector3.Down,Vector3.Forward,Vector3.Backward,Vector3.Left,Vector3.Right})
{
var extent=System.MathF.Abs(dir.x)*bounds.Size.x+System.MathF.Abs(dir.y)*bounds.Size.y+System.MathF.Abs(dir.z)*bounds.Size.z;
var from=r.WorldTransform.PointToWorld(center+dir*(extent*.5f+12));
var to=r.WorldTransform.PointToWorld(center-dir*extent*.5f);
var trace=Scene.Trace.Sphere(.35f,from,to).WithSurfaceMeshes().WithoutTags("paintball_debris").Run();
if(!trace.Hit||trace.GameObject!=r.GameObject)continue;
system.Spawn(trace,Color.Magenta);found=true;hitCount++;break;
}
if(!found && r.GameObject.Name.Contains("roof",System.StringComparison.OrdinalIgnoreCase))
{
foreach(var x in new[]{-.4f,-.2f,.2f,.4f})
foreach(var y in new[]{-.4f,-.2f,.2f,.4f})
{
var roofPoint=r.WorldTransform.PointToWorld(center+new Vector3(bounds.Size.x*x,bounds.Size.y*y,0));
var t=Scene.Trace.Ray(roofPoint-Vector3.Up*30,roofPoint+Vector3.Up*30).WithSurfaceMeshes().WithoutTags("paintball_debris").Run();
if(t.Hit&&t.GameObject==r.GameObject){system.Spawn(t,Color.Magenta);found=true;}
}
if(found)hitCount++;
}
tested++;Log.Info($"SURFACE_PAINT {(found ? "HIT" : "UNVERIFIED")} {r.GameObject.Name}");
}
Log.Info($"SURFACE_PAINT COMPLETE hit={hitCount} tested={tested}");
var glass=Scene.GetAllComponents<ModelRenderer>().First(x=>x.GameObject.Name=="Foundry skylight glazing");
var point=glass.WorldTransform.PointToWorld(glass.Model.Bounds.Center);
var glassHit=Scene.Trace.Ray(point-Vector3.Up*35,point+Vector3.Up*35).WithSurfaceMeshes().WithoutTags("paintball_debris").Run();
system.Clear();system.Spawn(glassHit,Color.Magenta);
var player=Scene.GetAllComponents<PlayerController>().First();player.UseCameraControls=false;
Scene.Camera.WorldPosition=glassHit.HitPosition+glassHit.Normal*45;
Scene.Camera.WorldRotation=Rotation.LookAt(-glassHit.Normal);Scene.Camera.FieldOfView=55;
Log.Info($"GLASS_PAINT hit={glassHit.GameObject?.Name} at={glassHit.HitPosition}");
}
}