/*
* 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>
*/
#pragma once
#include <Components/BoxComponent.h>
#include <GameFramework/ProjectileMovementComponent.h>
#include "TankProjectile.generated.h"

/// <summary>
/// The projectile (tank bullet) used by all of the tanks in the game.
/// </summary>
UCLASS(config=Game)
class ATankProjectile : public AActor
{
	GENERATED_BODY()

protected:

	/// <summary>
	/// The audio sound effect to play when the main cannon is fired.
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Audio")
	USoundBase* myTankExplosionAudio;

	/// <summary>
	/// The particle system to use for the engine exhaust heat effect.
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Particles")
	UParticleSystem* myTankHitParticles;

	/// <summary>
	/// The amount of damage to apply to the tank if this hits the tank.
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
	float myDamageToApply;

	/// <summary>
	/// The amount of force/impulse to apply to the tank when this is fired.
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
	float myImpuseToApply;

	/// <summary>
	/// The collision box used for this projectile.
	/// </summary>
	UPROPERTY(VisibleDefaultsOnly, Category = "Internal")
	UBoxComponent* myCollisionComponent;

	///The projectile component used for detecting collision with fast moving objects (such as a projectile)
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Internal", meta = (AllowPrivateAccess = "true"))
	UProjectileMovementComponent* myProjectileMovementComponent;

	/// <summary>
	/// The static mesh used by this projectile.
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Internal")
	UStaticMeshComponent* myStaticMeshComponent;

public:
	/// <summary>
	/// The default constructor for the tank projectile.
	/// </summary>
	ATankProjectile();

	/// <summary>
	/// Called when the scene/level first starts. Finds the static mesh component
	/// from the blueprint.
	/// </summary>
	virtual void BeginPlay() override;

	/// <summary>
	/// Called when this projectile collides with something. Depending on what it collides with, 
	/// there are different responses.
	/// 
	/// Here is the original comment from the parent function: Event called when a component hits 
	/// (or is hit by) something solid. This could happen due to things like Character movement, 
	/// using Set Location with 'sweep' enabled, or physics simulation. For events when objects 
	/// overlap(e.g.walking into a trigger) see the 'Overlap' event.
	///
	/// @note For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled for this component.
	/// @note When receiving a hit from another object's movement, the directions of 'Hit.Normal' and 'Hit.ImpactNormal'
	/// will be adjusted to indicate force from the other object against this object.
	/// @note NormalImpulse will be filled in for physics - simulating bodies, but will be zero for swept - component blocking collisions.
	/// </summary>
	/// <param name="hitComp">The specific component that was hit on this actor.</param>
	/// <param name="otherActor">The actor this projectile collided with.</param>
	/// <param name="otherComp">The specific component in otherActor that was hit.</param>
	/// <param name="normalImpulse">NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions.</param>
	/// <param name="hitResult">Structure containing information about one hit of a trace, such as point of impact and surface normal at that point.</param>
	UFUNCTION()
	virtual void OnHit(UPrimitiveComponent* hitComp, AActor* otherActor, UPrimitiveComponent* otherComp, FVector normalImpulse, const FHitResult& hitResult);

	/// <summary>
	/// Plays exploding sound effect, starts explosion particles, and destroys/removes the projectile.
	/// </summary>
	void ExplodeAndDestroy();

	/// <summary>
	/// Returns the ammount of impulse generated by shooting the projectile.
	/// </summary>
	/// <returns>The ammount of impulse generated by shooting the projectile.</returns>
	float GetImpulseToApply() const;

	/// <summary>
	/// Returns a pointer to this projectile's Projectile Movement Component.
	/// </summary>
	/// <returns>A pointer to this projectile's Projectile Movement Component.</returns>
	UProjectileMovementComponent* GetProjectileMovementComponent() const;
};

