ShieldScoreReview.cs
using Sandbox;
using System.Collections.Generic;
namespace PaintballBaddies;
/// <summary>Opt-in native projectile regression; isolated above the playable arena.</summary>
public sealed class ShieldScoreReview : Component
{
private GameObject actorObject, shooterObject, shieldObject;
private PaintballCombatant actor, attacker;
private ArenaShield shield;
private float elapsed;
private int shots;
public bool Done { get; private set; }
public List<string> Results { get; } = new();
protected override void OnStart()
{
actorObject=new GameObject(GameObject){Name="Shield test wearer",WorldPosition=new Vector3(0,0,1500)};
actor=actorObject.Components.Create<PaintballCombatant>();actor.Team=91;actor.StayInMatch=true;
var shape=actorObject.Components.Create<BoxCollider>();shape.Scale=new Vector3(28,28,66);shape.Center=new Vector3(0,0,33);
shooterObject=new GameObject(GameObject){Name="Shield test shooter",WorldPosition=new Vector3(100,0,1565)};
attacker=shooterObject.Components.Create<PaintballCombatant>();attacker.Team=92;attacker.StayInMatch=true;
shieldObject=new GameObject(GameObject){Name="Shield scoring test panel"};shield=shieldObject.Components.Create<ArenaShield>();
}
protected override void OnUpdate()
{
if(Done)return;
elapsed+=Time.Delta;
if(elapsed<.2f)return;
elapsed=0;
if(shots==0 && shield.Owner!=actor){shield.Collect(actor);return;}
if(shots>0)
{
bool pass=shots<=5 ? actor.PaintHits==0 && attacker.HitsLanded==0 && shield.Remaining==5-shots
: actor.PaintHits==shots-5 && attacker.HitsLanded==shots-5;
if(shots==5)pass=pass && shield.Shatters==1 && !shield.Owner.IsValid() && Scene.GetAllComponents<ShieldBreakEffect>().Sum(x=>x.Fragments)==16;
var result=$"{(pass ? "PASS" : "FAIL")} shot={shots} shield={shield.Remaining} received={actor.PaintHits} landed={attacker.HitsLanded} paint={shield.PaintCount}";
Results.Add(result);Log.Info("SHIELD_SCORE "+result);
}
if(shots>=6){Done=true;return;}
var target=actorObject.WorldPosition+Vector3.Up*65; // Exposed helmet zone above the visible panel.
var start=target+Vector3.Forward*100;
var go=new GameObject(GameObject){Name="Shield score physical paintball",WorldPosition=start};
var ball=go.Components.Create<OpponentPaintball>();ball.Shooter=shooterObject;ball.Team=92;ball.Velocity=PaintballFlight.LaunchVelocity(start,target);
shots++;
}
protected override void OnDestroy()
{
// Broken shields deliberately detach from their wearer.
if(shieldObject.IsValid())shieldObject.Destroy();
}
}