PisadaGigante.cs

Component attached to a prefab that converts character Step events and landing events into camera shakes and an optional landing sound. It exposes properties for shake strength, radius, landing multiplier, and an optional SoundEvent, and it attenuates shake by squared distance to the scene camera.

NetworkingFile Access
namespace SBH;

using Sandbox;

/// <summary>
/// [SBHBase] PISADA DE GIGANTE (2026-08-10, para el Siren Head — y todo
/// coloso que venga). Colgado en el prefab, convierte cada evento Step del
/// personaje en un TEMBLOR de pantalla con caída por distancia, y el
/// ATERRIZAJE de un salto/caída en un pisotón más fuerte todavía (con su
/// sonido propio, porque el aterrizaje no es un evento pintado).
///
/// El sonido de las pisadas normales va como siempre: pintando los Step en
/// el editor con el Dato apuntando al .sound del personaje (p. ej.
/// sounds/sirenhead/pisada_gigante.sound).
/// </summary>
public sealed class PisadaGigante : Component
{
	[Property, Description( "Trauma de temblor por pisada (0.1 apenas se siente, 0.5 sacude fuerte) — se atenúa con la distancia" )]
	public float FuerzaTemblor { get; set; } = 0.35f;

	[Property, Description( "Distancia a la que el temblor deja de sentirse (el sonido tiene su propia distancia en el .sound)" )]
	public float RadioTemblor { get; set; } = 2500f;

	[Property, Description( "Multiplicador del temblor al ATERRIZAR de un salto o caída" )]
	public float MultAterrizaje { get; set; } = 2.5f;

	[Property, Description( "Sonido del aterrizaje (opcional): suena al caer aunque no haya evento pintado" )]
	public SoundEvent SonidoAterrizaje { get; set; }

	/// <summary> Lo llama el despachador de eventos en cada Step del personaje. </summary>
	public void AlPaso( Vector3 punto ) => Sacudir( punto, FuerzaTemblor );

	/// <summary> Lo llaman SaltoNextbot y la posesión al tocar el piso tras un vuelo. </summary>
	public void AlAterrizar()
	{
		if ( SonidoAterrizaje != null )
			Sound.Play( SonidoAterrizaje, WorldPosition );

		Sacudir( WorldPosition, FuerzaTemblor * MultAterrizaje );
	}

	void Sacudir( Vector3 punto, float fuerza )
	{
		var cam = Scene?.Camera;
		if ( !cam.IsValid() ) return;

		var distancia = cam.WorldPosition.Distance( punto );
		if ( distancia >= RadioTemblor ) return;

		// Atenuación cuadrática: de cerca sacude entero, de lejos un cosquilleo
		var cerca = 1f - (distancia / RadioTemblor);
		TemblorCamara.Sacudir( Scene, fuerza * cerca * cerca );
	}
}