/*
* Neural Tanks is a game created by Eddie O'Hagan that leverages Neural Networking
* to use for AI. This was created in Unreal Engine 4 which is developed by Epic Games.
* (Copyright Epic Games, Inc. All Rights Reserved.)
*
* Smart Tanks was originally developed by Mat Buckland in 2002 as an example
* on how Neural Networking can be used to train a set of minesweepers
* to collect mines. I (Eddie O'Hagan) updated this project in 2024 to use more
* Object Oriented Programming and modern practices. To see the original tutorial;
* visit <see href="http://www.ai-junkie.com/ann/evolved/nnt1.html">Neural Networking Tutorial</see>
* and <see href="http://www.ai-junkie.com/ga/intro/gat1.html">Genetic Algorithm Tutorial</see>
*/
#include "BossAITankPawn.h"
#include <Kismet/GameplayStatics.h>

/// <summary>
/// Called when this Boss AI Tank is first spawned into the world/level.
/// </summary>
void ABossAITankPawn::BeginPlay()
{
	Super::BeginPlay();

	myHasBeenHitOnce = false;
	myIsLinePlaying = false;

	myAudioComponent = Cast<UAudioComponent>(GetComponentByName("VoiceAudioComponent"));
	if (myAudioComponent != NULL)
	{
		myAudioComponent->OnAudioPlayStateChanged.AddUniqueDynamic(this, &ABossAITankPawn::OnPlayStateChanged);
	}
}

/// <summary>
/// Called when this Boss AI Tank is hit with a projectile. 
/// Handles damage and playing voice lines.
/// </summary>
/// <param name="theAttackingPawn">The Tank that shot this Boss AI Tank.</param>
/// <param name="damage">The amount of damage caused by the shot.</param>
void ABossAITankPawn::OnTankHit(ATankPawn* theAttackingPawn, float damage)
{
	//Instead of destroying the tank (like in the parent of this class), allow the cinematic/sequence to destroy the tank.
	ATankPawn::OnTankHit(theAttackingPawn, damage);

	//Apply the specified amount of damage to this tank.
	DamageTank(damage);

	//Check if this boss has lost all its health points (HP).
	if (myCurrentHealthPoints <= 0.0f)
	{
		//Setting the fitness negative will remove it from the pool and trigger the end of the round.
		SetFitness(-1.0);
	}

	if (myAudioComponent != NULL)
	{
		if (myIsLinePlaying == false)
		{
			//Check if we need to play the voice line for when this Boss is first hit.
			if (myHasBeenHitOnce == false)
			{
				myAudioComponent->SetSound(myOnFirstHitVoiceLine);
				myAudioComponent->Play();

				myHasBeenHitOnce = true;
			}
			else
			{
				//Only play a voice line 1/3rd of the time so it's not annoying.
				if (FMath::RandRange(1, 3) == 1)
				{
					//Pick and Play a random voice line from the collection.
					myAudioComponent->SetSound(myRandomVoiceLines[FMath::RandRange(0, myRandomVoiceLines.Num() - 1)]);
					myAudioComponent->Play();
				}
			}
		}
	}
}

/// <summary>
/// Called when the currently playing audio changes stat, such as being stopped,
/// paused, or starts playing. This allows us to keep track of when a voice line
/// is currently being played or not.
/// </summary>
/// <param name="thePlayState">The updated state for the audio.</param>
void ABossAITankPawn::OnPlayStateChanged(EAudioComponentPlayState thePlayState)
{
	if (thePlayState == EAudioComponentPlayState::Stopped)
	{
		myIsLinePlaying = false;
	}
	else if (thePlayState == EAudioComponentPlayState::Playing)
	{
		myIsLinePlaying = true;
	}
}

/// <summary>
/// Stops all voice lines from playing. This is used when the Boss AI Tank
/// dies and we transition to a cutscene/cinematic.
/// </summary>
void ABossAITankPawn::StopAllVoiceLines()
{
	myAudioComponent->Stop();
}