Effects/SnipeZone.cs
using System;
namespace PlanetMeat;
[Group( "Planet Meat - Effects" ), Title( "Snipe Zone" ), Icon( "location_searching" )]
public sealed class SnipeZone : Component
{
public const int STAGE_INDEX_ARRIVING = 0;
public const int STAGE_INDEX_SNIPING = 1;
// RequireComponent doesn't make this stick... for some reason
[RequireComponent] public AutoWeapon Weapon { get => field ??= Components.Get<AutoWeapon>(); set; }
[RequireComponent] public Targeter Targeter { get; set; }
[RequireComponent] public DelayedStages Delay { get; set; }
[Property] float DriftSpeed { get; set; } = 250.0f;
[Property] float DriftScatter { get; set; } = 0.25f;
[Property] float DepatureTime { get; set; } = 2.5f;
public float DriftAngle
{
get
{
if ( float.IsNaN( field ) )
field = Game.Random.Float( 2.0f * MathF.PI );
return field;
}
private set;
} = float.NaN;
[Property]
public float Duration { get; set; } = 20.0f;
private TimedRing Ring { get; set; }
public void ApplyConfig( float delay, float durationMult, int dmgPerShot, float steadiness, float radius )
{
var drift = 1.0f - steadiness;
DriftSpeed *= drift;
DriftScatter *= drift;
Weapon.BaseDamage = dmgPerShot;
Targeter.BaseRange = (int)Math.Ceiling( radius );
Delay.Delay = delay;
Duration *= durationMult;
}
protected override void OnStart()
{
base.OnStart();
Weapon.Enabled = false;
Delay.DestroyAfter = DepatureTime;
Delay.StageStarted += OnStageStarted;
Ring = TimedRing.Create( WorldPosition, Weapon.Targeter.Range );
Ring.StartBasicTimer( Delay.Delay, false );
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( Delay.StageIndex == STAGE_INDEX_SNIPING )
{
var spread = DriftScatter * MathF.PI * Time.Delta;
DriftAngle += Game.Random.Float( -spread, spread );
WorldPosition += new Vector3( Vector2.FromRadians( DriftAngle ) ) * DriftSpeed * Time.Delta;
Ring.WorldPosition = WorldPosition;
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if ( Ring?.GameObject is GameObject ringGo && ringGo.IsValid )
ringGo.Destroy();
}
public void OnStageStarted( int stage )
{
Weapon.Enabled = stage == STAGE_INDEX_SNIPING;
switch ( stage )
{
case STAGE_INDEX_SNIPING:
Delay.Delay = Duration;
Ring.StartBasicTimer( Duration, true );
break;
case DelayedStages.STAGE_INDEX_DESTROY:
Ring?.GameObject.Destroy();
Ring = null;
break;
}
}
}