things/items/Magnet.cs

An Item subclass representing a magnet pickup in the game. It sets lifetime, physics parameters, per-instance rotation/float animation, and grants a magnet to a player on collision then removes itself.

Native Interop
using System;
using Sandbox;
using Sandbox.Diagnostics;
using Sandbox.Utility;

public class Magnet : Item
{
	private float _rotateTimeOffset;
	private float _personalRotateSpeed;

	public override Vector3 SpawnScale => new Vector3( 0.8f );
	protected override float AttractRangeFactor => 0.9f;
	protected override float AttractStrengthFactor => 0.6f;

	public bool HasBeenUsed { get; private set; }

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

		Lifetime = 85f;
		ShouldCheckBounds = true;
		PushStrength = 500f;

		BaseZPos = -15f;
		WorldPosition = WorldPosition.WithZ( BaseZPos );

		if ( IsProxy )
			return;

		Deceleration = 0.92f;

		_rotateTimeOffset = Game.Random.Float( 0f, 10f );
		_personalRotateSpeed = Game.Random.Float( 4f, 8f );
	}

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

		if ( Manager.Instance.IsGameOver )
			return;

		if ( IsProxy )
			return;

		LocalRotation = Rotation.From( new Angles( 0f, -90f, Utils.FastSin( _rotateTimeOffset + Time.Now * _personalRotateSpeed ) * 7f ) );

		if ( !IsInTheAir )
			WorldPosition = WorldPosition.WithZ( BaseZPos + 3f + Utils.MapReturn( Utils.FastSin( _rotateTimeOffset + Time.Now * _personalRotateSpeed ), -1f, 1f, -1f, 1f, EasingType.Linear ) * 3f );
	}

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

		if ( CantBeCollected || HasBeenUsed )
			return;

		if ( other is Player player )
		{
			if ( !player.IsDead )
			{
				player.GetMagnet();

				player.CollectItemEffect();

				HasBeenUsed = true;

				Remove();
			}
		}
	}
}