things/ReviveSoul.cs
using Sandbox;
using static Manager;
public class ReviveSoul : Thing
{
public TimeSince SpawnTime { get; private set; }
public float Lifetime { get; set; }
private TimeSince _timeSinceBlink;
protected override void OnAwake()
{
base.OnAwake();
//OffsetY = -0.14f;
Scale = 0.6f;
ShadowOpacity = 0.8f;
ShadowScale = 0.8f;
SpawnShadow( ShadowScale, ShadowOpacity );
if ( IsProxy )
return;
//BasePivotY = 0.225f;
SpawnTime = 0f;
Lifetime = 60f;
Radius = 0.175f;
CollideWith.Add( typeof( Enemy ) );
CollideWith.Add( typeof( Player ) );
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( !Manager.Instance.ShouldUpdateThings )
return;
Sprite.LocalScale = new Vector3( Scale + MathF.Cos( SpawnTime * 8f ) * 0.025f, Scale + Utils.FastSin( SpawnTime * 8f ) * 0.025f, 1f ) * Globals.SPRITE_SCALE;
ShadowScale = 0.8f + Utils.FastSin( SpawnTime * 8f ) * 0.035f;
ShadowSpriteDirty = true;
float opacity = 0.3f + Utils.FastSin( SpawnTime * 5f ) * 0.2f;
Sprite.Tint = Color.White.WithAlpha( opacity );
ShadowSprite.Tint = Color.Black.WithAlpha( opacity );
if ( IsProxy )
return;
float dt = Time.Delta;
Position2D += Velocity * dt;
Position2D = new Vector2( MathX.Clamp( Position2D.x, Manager.Instance.BOUNDS_MIN.x + Radius, Manager.Instance.BOUNDS_MAX.x - Radius ), MathX.Clamp( Position2D.y, Manager.Instance.BOUNDS_MIN.y + Radius, Manager.Instance.BOUNDS_MAX.y - Radius ) );
WorldPosition = WorldPosition.WithZ( Globals.GetZPos( Position2D.y ) );
Velocity *= (1f - dt * 3.5f);
if ( SpawnTime > Lifetime - 7f )
{
if ( _timeSinceBlink > Utils.Map( SpawnTime, Lifetime - 7f, Lifetime, 0.25f, 0.03f, EasingType.SineIn ) )
{
_timeSinceBlink = 0f;
Sprite.Enabled = !Sprite.Enabled;
}
if ( SpawnTime > Lifetime )
{
var cloud = Manager.Instance.SpawnCloud( Position2D );
cloud.Velocity = new Vector2( Game.Random.Float( -1f, 1f ), Game.Random.Float( -1f, 1f ) ).Normal * Game.Random.Float( 0.2f, 0.6f );
Remove();
return;
}
}
if ( SpawnTime > 0.1f )
{
foreach ( Player player in Manager.Instance.GetPlayers( alive: false ) )
{
var dist_sqr = (Position2D - player.Position2D).LengthSquared;
var req_dist_sqr = MathF.Pow( player.Stats[PlayerStat.CoinAttractRange], 2f );
if ( dist_sqr < req_dist_sqr )
{
Velocity += (player.Position2D - Position2D).Normal * Utils.Map( dist_sqr, req_dist_sqr, 0f, 0f, 1f, EasingType.Linear ) * player.Stats[PlayerStat.CoinAttractStrength] * dt;
}
}
}
for ( int dx = -1; dx <= 1; dx++ )
{
for ( int dy = -1; dy <= 1; dy++ )
{
Manager.Instance.HandleThingCollisionForGridSquare( this, new GridSquare( GridPos.x + dx, GridPos.y + dy ), dt );
if ( IsRemoved )
return;
}
}
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
if ( other is Player player && SpawnTime > 0.1f )
{
if ( player.IsDead )
{
player.Revive();
Manager.Instance.PlaySfxNearby( "heal", Position2D, pitch: Utils.Map( player.Health / player.Stats[PlayerStat.MaxHp], 0f, 1f, 1.5f, 1f ), volume: 1.5f, maxDist: 5f );
Remove();
}
else
{
Velocity += (Position2D - player.Position2D).Normal * Utils.Map( percent, 0f, 1f, 0f, 1f ) * player.Stats[PlayerStat.PushStrength] * (1f + player.TempWeight) * dt;
}
}
}
}