things/orbiters/OrbiterLens.cs

A game Thing subclass, an orbital lens entity that orbits a Unit. It tints and scales the model based on whether it has an owner, updates orbit distance and rotation to follow the orbited unit, and buffs bullets that collide with it by increasing their damage.

Networking
using System;
using Sandbox;

public class OrbiterLens : Orbiter
{
	[Sync] public float DamagePercent { get; set; }

	private TimeSince _timeSinceBuff;

	private float _lastAlpha;

	protected override void OnStart()
	{
		base.OnStart();

		if ( IsProxy )
			return;

		CollideWithTags.Add( "bullet" );

		OrbitDistance = 35f;

		_lastAlpha = -1f;
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();

		float alpha = OrbitedUnit.IsValid() && !OrbitedUnit.IsDying
			? 0.5f
			: 0f;

		if ( alpha != _lastAlpha )
		{
			Model.Tint = Model.Tint.WithAlpha( alpha );
			_lastAlpha = alpha;
		}

		if ( IsProxy )
			return;

		if ( !OrbitedUnit.IsValid() || OrbitedUnit.IsDying )
			return;

		WorldRotation = Rotation.LookAt( Position2D - OrbitedUnit.Position2D );

		OrbitDistance = OrbitedUnit.Radius + 35f;

		if ( _timeSinceBuff < 0.3f )
		{
			WorldScale = new Vector3( Utils.Map( _timeSinceBuff, 0f, 0.275f, 1.3f, 1f, EasingType.SineOut ) );
		}
	}

	protected override float GetZPos()
	{
		return OrbitedUnit.WorldPosition.z + 45f * (1f + Utils.FastSin( Time.Now * 6f ) * 0.185f);
	}

	public override void Colliding( Thing other, float percent, float dt )
	{
		base.Colliding( other, percent, dt );

		if ( !OrbitedUnit.IsValid() || OrbitedUnit.IsDying )
			return;

		if ( other is Bullet bullet && !bullet.IsLensBuffed )
		{
			bullet.LensBuff( 1f + DamagePercent );
			WorldScale = new Vector3( 1.3f );
			_timeSinceBuff = 0f;
		}
	}
}