PebbleComponent.cs
using System;
using Sandbox;
namespace Battlebugs;
public sealed class PebbleComponent : Component, Component.ICollisionListener
{
[RequireComponent] Rigidbody Rigidbody { get; set; }
[Property] GameObject ParticlePrefab { get; set; }
[Property] int HitCount { get; set; } = 1;
[Sync] public float Damage { get; set; } = 4f;
List<BugSegment> HitSegments = new();
List<CellComponent> HitCells = new();
public TimeSince TimeSinceCreated = 0;
TimeSince timeSinceMoving = 0;
public void LaunchAt( Vector3 target )
{
var time = Random.Shared.Float( 1.8f, 2f );
var vector = target - WorldPosition.WithZ( target.z );
var direction = vector.Normal;
var velocity = vector / time;
var verticalForce = -Scene.PhysicsWorld.Gravity.z * time / 2f;
velocity += Vector3.Up * verticalForce;
Rigidbody.Velocity = velocity;
Rigidbody.AngularVelocity = Vector3.Random * 10f;
}
protected override void OnFixedUpdate()
{
if ( IsProxy ) return;
if ( TimeSinceCreated > 10f )
{
GameObject.Destroy();
}
if ( Rigidbody.Velocity.Length > 1f )
{
timeSinceMoving = 0;
}
else if ( timeSinceMoving > 0.5f )
{
HitCount = 0;
Hit();
}
}
public void OnCollisionStart( Collision collision )
{
if ( IsProxy ) return;
if ( collision.Other.GameObject.Tags.Has( "pebble" ) ) return;
// Enable friction after hitting something
Rigidbody.LinearDamping = 2.5f;
Rigidbody.AngularDamping = 2f;
if ( collision.Other.GameObject.Components.TryGet<BugSegment>( out var segment ) )
{
if ( HitSegments.Contains( segment ) ) return;
HitSegments.Add( segment );
GameManager.Instance.BroadcastDamageNumber( WorldPosition, Damage );
segment.Damage( Damage );
Hit();
}
else if ( collision.Other.GameObject.Components.TryGet<CellComponent>( out var cell ) )
{
if ( HitCells.Contains( cell ) ) return;
if ( cell.IsHit ) return;
HitCells.Add( cell );
cell.BroadcastHit();
HitCount--;
if ( HitCount == 0 ) Hit();
}
}
void Hit()
{
HitCount--;
if ( HitCount <= 0 )
{
BroadcastDestroyEffect();
GameObject.Destroy();
}
}
[Rpc.Broadcast]
void BroadcastDestroyEffect()
{
Sound.Play( "break-rocks", WorldPosition );
if ( ParticlePrefab is not null )
{
ParticlePrefab.Clone( WorldPosition );
}
}
}