perks/CurseLavaBlob.cs

A unique curse perk that periodically spawns a lava blob near the player. It tracks time, chooses a target direction/position, requests the Manager to spawn the lava puddle and plays a nearby sound, and updates UI display values.

NetworkingFile Access
using System;
using Sandbox;

[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseLavaBlob : Perk
{
	private const float INTERVAL = 20f;

	private TimeSince _timeSinceLava;

	static CurseLavaBlob()
	{
		Register<CurseLavaBlob>(
			name: "Magma Flow",
			imagePath: "textures/icons/vector/curse_lava_blob.png",
			description: level => $"A lava blob lands\nnearby every [-]{(int)INTERVAL}s[/-]"
		);
	}

	public override void Start()
	{
		base.Start();

		ShouldUpdate = true;

		HighlightColor = new Color( 1f, 0.3f, 0f );
		HighlightDuration = 0.75f;
		HighlightOpacity = 3.5f;

		DisplayCooldownColor = new Color( 1f, 0.35f, 0.1f );

		_timeSinceLava = 0f;
	}

	public override void Update( float dt )
	{
		base.Update( dt );

		if ( _timeSinceLava > INTERVAL )
		{
			var vel = Player.Velocity;
			var dir = vel.LengthSquared > 0f
				? vel.Normal
				: Utils.GetRandomVector();

			var targetPos = Player.Position2D + Utils.GetRandomVectorInCone( dir, 120f ) * Game.Random.Float( 30f, 100f );

			Manager.Instance.SpawnLavaBlob(
				Player.Position2D,
				targetPos,
				puddleRadius: Game.Random.Float( 130f, 200f ),
				enemySource: null,
				enemyType: EnemyType.None
			);

			_timeSinceLava = 0f;

			Highlight();

			IconScale = Game.Random.Float( 1.1f, 1.25f );
			IconAngleOffset = Game.Random.Float( 6f, 10f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);

			Manager.Instance.PlaySfxNearbyRpc( "lava_puddle_03", Player.Position2D, pitch: Game.Random.Float( 0.9f, 1.1f ), volume: 0.8f, maxDist: 350f );
		}

		DisplayText = $"{MathX.CeilToInt( INTERVAL - _timeSinceLava )}";
		DisplayCooldown = Utils.Map( _timeSinceLava, 0f, INTERVAL, 0f, 1f );
	}
}