A Component named River that tracks Thing instances touching the river using a Dictionary<Thing,int>. On each update it iterates touching Things, removes invalid ones, skips those with IgnoreCollision, and damps their Velocity toward zero. It also exposes Restart, OnTriggerEnter and OnTriggerExit to manage the touch counts.
using Sandbox;
using System;
using static Sandbox.VertexLayout;
public sealed class River : Component
{
public Dictionary<Thing, int> Touching = new();
protected override void OnUpdate()
{
//Gizmo.Draw.Color = Color.White;
//Gizmo.Draw.Text( $"Touching: {Touching.Count}", new global::Transform( WorldPosition ) );
var dt = Time.Delta;
for ( int i = Touching.Keys.Count - 1; i >= 0; i-- )
{
var other = Touching.Keys.ElementAt( i );
if ( !other.IsValid() )
{
Touching.Remove( other );
continue;
}
if ( other.IgnoreCollision )
continue;
other.Velocity = Utils.DynamicEaseTo( other.Velocity, Vector3.Zero, 0.06f, dt );
}
}
public void Restart()
{
Touching.Clear();
}
public void OnTriggerEnter( Thing thing )
{
if ( Touching.ContainsKey( thing ) )
Touching[thing]++;
else
Touching.Add( thing, 1 );
}
public void OnTriggerExit( Thing thing )
{
if ( !Touching.ContainsKey( thing ) )
return;
Touching[thing]--;
if( Touching[thing] <= 0 )
Touching.Remove( thing );
}
}