Network/WaterRiver.cs

A data class representing a river segment between two nodes in a water network. Stores endpoint node ids, bezier tangents, widths, speed, wave strength and depth, and provides small helpers for node membership and width lookup.

NetworkingFile Access
using Sandbox;

namespace RedSnail.WaterTool2;

/// <summary>
/// A river between two nodes: a cubic Bezier whose handles hang off the nodes. The water always flows from the start
/// node to the end node, so a river reads upstream to downstream; reversing a river swaps its ends.
/// </summary>
public sealed class WaterRiver
{
	public const float MinWidth = 32.0f;
	public const float MaxWidth = 16384.0f;

	public int Id { get; set; }

	/// <summary>
	/// The upstream node.
	/// </summary>
	public int StartNodeId { get; set; }

	/// <summary>
	/// The downstream node.
	/// </summary>
	public int EndNodeId { get; set; }

	/// <summary>
	/// Bezier handle leaving the start node into the river (P1 - P0).
	/// </summary>
	public Vector3 StartTangent { get; set; }

	/// <summary>
	/// Bezier handle leaving the end node into the river (P2 - P3).
	/// </summary>
	public Vector3 EndTangent { get; set; }

	/// <summary>
	/// Width at the upstream end. The banks ease from this to <see cref="EndWidth"/> along the river.
	/// </summary>
	[Range(MinWidth, 4000.0f)] public float StartWidth { get; set { field = value.Clamp(MinWidth, MaxWidth); } } = 400.0f;

	/// <summary>
	/// Width at the downstream end.
	/// </summary>
	[Range(MinWidth, 4000.0f)] public float EndWidth { get; set { field = value.Clamp(MinWidth, MaxWidth); } } = 400.0f;

	/// <summary>
	/// How fast the water runs on level ground, in units per second. A river with nothing flowing into it starts at
	/// this speed; slopes speed the water up and it settles back towards this on the flat. Rivers joining another
	/// carry their own speed into it.
	/// </summary>
	[Range(0.0f, 1000.0f)] public float Speed { get; set { field = value.Clamp(0.0f, 10000.0f); } } = 120.0f;

	/// <summary>
	/// Wave strength, relative to the network's wave profile (a lake is 1 by default). Rivers are usually calmer than
	/// the lakes they run into; the change is blended where they meet.
	/// </summary>
	[Range(0.0f, 2.0f)] public float Waves { get; set { field = value.Clamp(0.0f, 10.0f); } } = 0.35f;

	/// <summary>
	/// How deep the water is under its surface. Only gameplay reads it: swimming, drowning and buoyancy.
	/// </summary>
	[Range(10.0f, 2000.0f)] public float Depth { get; set { field = value.Clamp(1.0f, 100000.0f); } } = 250.0f;



	public bool Touches(int _NodeId)
	{
		return StartNodeId == _NodeId || EndNodeId == _NodeId;
	}



	public int OtherNodeId(int _NodeId)
	{
		return StartNodeId == _NodeId ? EndNodeId : StartNodeId;
	}



	/// <summary>
	/// The width at one of the river's ends, by node.
	/// </summary>
	public float WidthAt(int _NodeId)
	{
		return StartNodeId == _NodeId ? StartWidth : EndWidth;
	}
}