//=============================================================================
//
//	geizer1_nohelpmessages.txt
//
//	This is the script for the first encounter with Geizer, the E1M1 boss.
//	In this encounter, he simply follows the player outside of a hallway
//	His X and Y position do not change, but his Z position always matches
//	that of the player. Every few seconds, he attacks, and his attack must
//	be ducked under, or the player must hide behind a wall.
//
//	For documentation on scripting, please consult the Wrack Wiki at:
//	http://wrack.wikia.com/
//
//=============================================================================

#include "commondefines.h"


#define	THRUST_HORIZONTAL	15
#define	THRUST_VERTICAL		40

//== STATE PROTOTYPES =========================================================

state	Spawn;
state	Intro;
state	Main;
state	Warmup;
state	Attack;
state	CoolDown;
state	Lower;
state	Raise;
state	Killed;

//== VARIABLES ================================================================

int	g_iStartupTicks;

// Is Geizer in the middle of his attack that must be crouched under?
int	g_iLowerAttack;

//== EVENTS ===================================================================

event_instant( "killed" )
	ChangeState( Killed );

//-----------------------------------------------------------------------------
event_instant( "gibbed" )
	ChangeState( Killed );

//-----------------------------------------------------------------------------
event_instant( "player revived" )
{
	// Destroy gibs, puddles, etc.
	DestroyChildren( );

	DestroySelf( );
}

//-----------------------------------------------------------------------------
event_instant( "player continued" )
{
	// Destroy gibs, puddles, etc.
	DestroyChildren( );

	DestroySelf( );
}



int CalcHorizontalGibThrust( void )
{
	return (( rand( 0, RAND_MAX ) - ( RAND_MAX / 2 )) * 2 * THRUST_HORIZONTAL );
}

//-----------------------------------------------------------------------------
int CalcVerticalGibThrust( void )
{
	return ( rand( 0, RAND_MAX ) * 2 * ( THRUST_VERTICAL / 2 ));
}
//== STATES ===================================================================

state Spawn
{
	MainLoop
	{
		// Initialize some global variables.
		g_iLowerAttack = -1;
		g_iStartupTicks = -1;

		ChangeState( Intro );
	}
}

//-----------------------------------------------------------------------------
state Intro
{
	event( "animation over" )
	{
		// Play the idle sound, and have it play the entire time Geizer
		// is alive.
		PlaySound( "geizer1_idle.wav", 100, SFXF_LOOP, SFXPRIORITY_MEDIUM );

		changestate( Main );
	}

	OnEnter
	{
		// Play our intro animation.
		SetAnimation( "Intro", -1, 0 );

		// Play our intro sound.
		PlaySound( "geizer1_intro.wav", 100, 0, SFXPRIORITY_HIGHEST );

		// Make us invulnerable while we do our intro.
		AddFlag( FLAG_IMMUNETODAMAGE );
		AddFlag( FLAG_NOCOLLISIONAGAINST );
		Delay (300);
		
		ClearFlag( FLAG_IMMUNETODAMAGE );
		ClearFlag( FLAG_NOCOLLISIONAGAINST );
	}

	MainLoop
	{
	}

	OnExit
	{

		// Interpolate between our start position and desired position
		// for three seconds (180 frames).
		g_iStartupTicks = 180;
	}
}

//-----------------------------------------------------------------------------
state Main
{
	int	iTick;

	OnEnter
	{
		// Play our idle animation animation.
		if ( g_iLowerAttack != 1 )
			SetAnimation( "Idle", -1, ANIMF_LOOP );

		// Determine when to attack.
		if ( GetSkillSettingFlags( ) & SKILL_VERYAGGRESSIVE )
			iTick = rand( 1, 5 ) * ( FPS / 2 );
		else if ( GetSkillSettingFlags( ) & SKILL_AGGRESSIVE )
			iTick = rand( 2, 8 ) * ( FPS / 2 );
		else
			iTick = rand( 4, 8 ) * ( FPS / 2 );
	}

	MainLoop
	{

		// Do our attack about once every 3 seconds.
		if ( iTick == 0 )
		{
			// Fire a set of missiles at our target.
			if ( rand( 0, 1 ) == 0 )
			{
				g_iLowerAttack = 1;
				ChangeState( Lower );
			}
			else
			{
				g_iLowerAttack = 0;
				ChangeState( Warmup );
			}
		}
		else
			iTick--;

		// Perform our movement. In this incarnation, Geizer constantly
		// maintains the same Z coordinate as his target.
		FollowTargetZ( true, g_iStartupTicks, 180 );
		if ( g_iStartupTicks > 0 )
			g_iStartupTicks--;
	}
}

//-----------------------------------------------------------------------------
state Warmup
{
	int	iBlink;
	int	iTick;

	onenter
	{
		// Play our attack sound.
		PlaySound( "geizer1_attack.wav", 100, 0, SFXPRIORITY_HIGHEST );

		iTick = 0;
		iBlink = 0;
		SetAnimation( "Attack_Start", 70, 0 );
	}

	mainloop
	{
		if ( iTick == 0 )
		{
			// When we've blinked 6 times, change to our attack
			// state.
			if ( iBlink == 6 )
				changestate( Attack );

			// In lieu of an animation, blink the turret in blue 3 times to
			// indicate that it's in its warmup.
			SetWarmupTicks( 5 );

			iBlink++;
			iTick = 10;
		}
		else
			iTick--;

		// Perform our movement. In this incarnation, Geizer constantly
		// maintains the same Z coordinate as his target.
		FollowTargetZ( true, g_iStartupTicks, 180 );
		if ( g_iStartupTicks > 0 )
			g_iStartupTicks--;
	}

	onexit
	{
		SetWarmupTicks( 0 );
	}
}

//-----------------------------------------------------------------------------
state Attack
{
	int	iNumShotsLeft;
	int	iDelay;

	OnEnter
	{
		iNumShotsLeft = 20;
		iDelay = 0;
		SetAnimation( "Attack_Loop", -1, ANIMF_LOOP );
	}

	MainLoop
	{
		if ( iDelay == 0 )
		{
			// If we've fired all of our shots, change back to our
			// main state.
			if ( iNumShotsLeft == 0 )
				changestate( CoolDown );

			// Fire a missile at the player.
			SetSpawnPosition( SPAWNPOSITION_INFRONT, GetIntProperty( "projectileheight" ), true, GetStringProperty( "Projectile" ));
			FireProjectile( GetStringProperty( "Projectile" ), 1, 0, 0 );
			iNumShotsLeft--;

			// Fire one every 2 frames.
			iDelay = ( FPS / 30 );
		}
		else
			iDelay--;

		// Perform our movement. In this incarnation, Geizer constantly
		// maintains the same Z coordinate as his target.
		FollowTargetZ( true, g_iStartupTicks, 180 );
		if ( g_iStartupTicks > 0 )
			g_iStartupTicks--;
	}
}

//-----------------------------------------------------------------------------
state CoolDown
{
	event( "animation over" )
	{
		if ( g_iLowerAttack == 1 )
			changestate( Raise );
		else
			changestate( Main );
	}

	OnEnter
	{
		// Play our cool down animation.
		SetAnimation( "Attack_End", -1, 0 );
	}

	MainLoop
	{
		// Perform our movement. In this incarnation, Geizer constantly
		// maintains the same Z coordinate as his target.
		FollowTargetZ( true, g_iStartupTicks, 180 );
		if ( g_iStartupTicks > 0 )
			g_iStartupTicks--;
	}
}

//-----------------------------------------------------------------------------
state Lower
{
	int	iZPosition;
	int	iYDistance;

	onenter
	{
		iYDistance = 0;
	}

	mainloop
	{
		// Move a bit lower so the player has to jump, rather than
		// crouch, over the projectiles.
		if ( iYDistance > -32 )
		{
			iYDistance--;
			iZPosition = GetZPosition( );
			MoveLinearFromOrigin( 0, iYDistance, 0 );
			SetZPosition( iZPosition );
			FollowTargetZ( true, g_iStartupTicks, 180 );
			if ( g_iStartupTicks > 0 )
				g_iStartupTicks--;
		}
		else
			changestate( Warmup );
	}
}

//-----------------------------------------------------------------------------
state Raise
{
	int	iZPosition;
	int	iYDistance;

	onenter
	{
		iYDistance = -32;

		// Play our idle animation animation.
		SetAnimation( "Idle", -1, ANIMF_LOOP );
	}

	mainloop
	{
		// Raise back up from being lowered.
		if ( iYDistance < 0 )
		{
			iYDistance++;
			iZPosition = GetZPosition( );
			MoveLinearFromOrigin( 0, iYDistance, 0 );
			SetZPosition( iZPosition );
			FollowTargetZ( true, g_iStartupTicks, 180 );
			if ( g_iStartupTicks > 0 )
				g_iStartupTicks--;
		}
		else
			changestate( Main );
	}
}

//-----------------------------------------------------------------------------
state Killed
{
	int	iRestoreOnRevive;
	int	iZPosition;
	int	iAnimation;
	int	iExplosionParticleTick;

	
	event_instant( "fade to white" )
		FadeToColor( 255, 255, 255, 60 );

	event( "animation over" )
	{
		if ( iAnimation == 0 )
		{
			SetAnimation( "Death_2", -1, 0 );
			iAnimation++;
		}
		else if ( iAnimation == 1 )
		{
			SetSpawnPosition( SPAWNPOSITION_FROMCENTER, GetIntProperty( "height" ) / 2, false, "" );
		SpawnParticles( "ExplosionParticle", 1, true, 0, ANGLE_90 * -1 );
		iExplosionParticleTick = 0;

		// Make our body disappear.
		AddFlag( FLAG_DONTRENDER );

		// Toss some gibs.
		SetSpawnPosition( SPAWNPOSITION_FROMCENTER, GetIntProperty( "height" ) / 2, false, "" );
		TossGib( "Geizer_Gib1", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib2", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib3", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib4", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib5", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib6", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib7", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib8", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		TossGib( "Geizer_Gib9", CalcHorizontalGibThrust( ), CalcVerticalGibThrust( ), CalcHorizontalGibThrust( ), true );
		FadeFromColor( 255, 255, 255, 60 );
			SetAnimation( "Death_3", -1, 0 );
			ClearFlag( FLAG_NOGRAVITY );
			ClearFlag( FLAG_NOCOLLISION );
		}
		
	}

	OnEnter
	{
		
		iExplosionParticleTick = 1;
		iRestoreOnRevive = 1;

		// In case we were in the middle of attack 2, reset our
		// Y position.
		iZPosition = GetZPosition( );
		MoveLinearFromOrigin( 0, 0, 0 );
		SetZPosition( iZPosition );
		FollowTargetZ( true, g_iStartupTicks, 180 );

		// Set this state's animation.
		SetAnimation( "Death_1", -1, ANIMF_DONTBLEND );
		iAnimation = 0;

		// Play our death sound.
		PlaySound( "geizer1_dead.wav", 100, SFXF_STOPEXISTING_ALL, SFXPRIORITY_HIGHEST );

		// Stop allowing other objects to collide with us.
		StopBlocking( );
		Delay (105);
		ExecuteMapScript( "Geizer1SpecialDeath", 0, 0, 0, 0 );
	}

	MainLoop
	{
		if ( iExplosionParticleTick )
		{
			iExplosionParticleTick--;
			if ( iExplosionParticleTick == 0 )
			{
				// Spawn an explosion particle.
				SetSpawnPosition( SPAWNPOSITION_FROMCENTER, GetIntProperty( "height" ) / 2, false, "" );
				SpawnParticles( "ExplosionParticle_Geizer21", 1, true, 0, ANGLE_90 * -1 );

				// Setup the timer to make another one.
				iExplosionParticleTick = rand( 6, 15 );
			}
		}
	}
}
