RestaurantChairDebris.cs
using Sandbox;
using System;
namespace PaintballBaddies;
/// <summary>Reuse the mounted wooden furniture fragments when chair art has no break data.</summary>
public sealed class RestaurantChairDebris : Component
{
private Vector3 velocity;
private float age;
private int bounces,round;
public static int Spawned {get;private set;}
public static void Spawn(Scene scene,Vector3 origin,Rotation rotation,int round)=>Spawn(scene,origin,rotation,round,1);
// A couple of small chips flying off a hit, without the break sound.
public static void Splinters(Scene scene,Vector3 point,int count,int round)
{
for(int i=0;i<count;i++)
{
var model=Model.Load($"models/props/trim_sheets/table/coffeetable_a_gib_{i%2+1:00}.vmdl");if(model.IsError)continue;
var direction=Rotation.FromYaw(Game.Random.Float(0,360)).Forward;
var go=new GameObject(false,"Wood splinter"){NetworkMode=NetworkMode.Never,WorldPosition=point+Vector3.Up*2,WorldRotation=Rotation.FromYaw(Game.Random.Float(0,360)),WorldScale=new Vector3(.12f)};
go.Tags.Add("paintball_debris");go.Components.Create<ModelRenderer>().Model=model;
var debris=go.Components.Create<RestaurantChairDebris>();debris.round=round;debris.velocity=direction*Game.Random.Float(60,120)+Vector3.Up*Game.Random.Float(80,150);
go.Enabled=true;
}
}
public static void Spawn(Scene scene,Vector3 origin,Rotation rotation,int round,float size)
{
foreach(var old in scene.GetAllComponents<RestaurantChairDebris>().OrderByDescending(d=>d.age).SkipLast(29).ToArray())old.GameObject.Destroy();
for(int i=0;i<6;i++)
{
var model=Model.Load($"models/props/trim_sheets/table/coffeetable_a_gib_{i%2+1:00}.vmdl");if(model.IsError)continue;
float angle=i*MathF.PI/3;var direction=new Vector3(MathF.Cos(angle),MathF.Sin(angle),0);
var go=new GameObject(false,"Broken wooden chair piece"){NetworkMode=NetworkMode.Never,WorldPosition=origin+direction*6+Vector3.Up*(14+i*3),WorldRotation=rotation*Rotation.FromYaw(i*61),WorldScale=new Vector3((i%2==0 ? .32f : .48f)*size)};
go.Tags.Add("paintball_debris");go.Components.Create<ModelRenderer>().Model=model;
var debris=go.Components.Create<RestaurantChairDebris>();debris.round=round;debris.velocity=direction*Game.Random.Float(85,150)+Vector3.Up*Game.Random.Float(90,170);
go.Enabled=true;Spawned++;
}
Sound.Play(new SoundEvent{Sounds=[SoundFile.Load($"sounds/physics/phys-impact-wood-{Game.Random.Int(1,4)}.vsnd")],Volume=.8f,Pitch=1.1f,Distance=900},origin);
}
protected override void OnUpdate()
{
age+=Time.Delta;
if(age>3.5f || MultiplayerSession.Find(Scene)?.RoundId!=round){GameObject.Destroy();return;}
if(bounces>=3)return;
float dt=MathF.Min(Time.Delta,.035f);velocity+=Vector3.Down*520*dt;
var end=WorldPosition+velocity*dt;var h=Scene.Trace.Sphere(2,WorldPosition,end).WithoutTags("paintball_actor","overdrive_enemy","paintball_debris").Run();
WorldPosition=h.Hit ? h.HitPosition+h.Normal*2 : end;
if(h.Hit){velocity=(velocity-2*velocity.Dot(h.Normal)*h.Normal)*.27f;bounces++;}
WorldRotation*=Rotation.From(new Angles(220,140,90)*dt);
}
}