A Thing-derived game object representing a moving "lava safe spot" zone. It controls spawn positioning, lifetime, vertical easing when appearing/disappearing, movement based on MoveDir and Speed, collision response that repels from other things, bounds reflection, and scaling that updates its radius from a SphereCollider.
using System;
using Sandbox;
public class LavaSafeSpot : Thing
{
[Property] public ModelRenderer ModelRenderer { get; set; }
//public override Vector3 SpawnScale => new Vector3( 4f, 4f, 1f );
public override bool UseSpawnScale => false;
public Vector2 MoveDir { get; set; }
public override bool BoundsCheckIncludesRadius => true;
public float Speed { get; set; }
public virtual float SpawnZPos => -15f;
public float Lifetime { get; set; }
protected override void OnStart()
{
base.OnStart();
ShouldCheckBounds = true;
WorldPosition = WorldPosition.WithZ( SpawnZPos );
if ( IsProxy )
return;
Lifetime = 60f;
CollideWithTags.Add( "lava_safe_spot" );
}
protected override void OnUpdate()
{
base.OnUpdate();
//Gizmo.Draw.Color = Color.White;
//Gizmo.Draw.Text( $"{Radius}", new global::Transform( WorldPosition ) );
if ( IsProxy )
return;
var spawnTime = 1.5f;
if(TimeSinceSpawn < spawnTime )
{
WorldPosition = WorldPosition.WithZ( Utils.Map( TimeSinceSpawn, 0f, spawnTime, SpawnZPos, 0f ) );
}
else if( TimeSinceSpawn > Lifetime - spawnTime )
{
WorldPosition = WorldPosition.WithZ( Utils.Map( TimeSinceSpawn, Lifetime - spawnTime, Lifetime, 0f, SpawnZPos ) );
}
WorldPosition += (Vector3)MoveDir * Speed * Time.Delta;
if(TimeSinceSpawn > Lifetime)
{
GameObject.Destroy();
}
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
MoveDir = (Position2D - other.Position2D).Normal;
}
protected override void OnOutOfBounds( Direction direction )
{
base.OnOutOfBounds( direction );
if ( direction == Direction.Left )
MoveDir = new Vector2( Math.Abs( MoveDir.x ), MoveDir.y );
else if ( direction == Direction.Right )
MoveDir = new Vector2( -Math.Abs( MoveDir.x ), MoveDir.y );
else if ( direction == Direction.Down )
MoveDir = new Vector2( MoveDir.x, Math.Abs( MoveDir.y ) );
else if ( direction == Direction.Up )
MoveDir = new Vector2( MoveDir.x, -Math.Abs( MoveDir.y ) );
}
public void SetScale(float scale)
{
WorldScale = new Vector3( scale, scale, 1f );
var sphereCollider = Collider as SphereCollider;
Radius = sphereCollider.Radius * WorldScale.x;
}
}