<commit_before>
#include "../Flare.h"
#include "FlareSpacecraft.h"
#include "../Game/FlareAsteroid.h"
#include "../Game/FlareGame.h"
#include "../Player/FlarePlayerController.h"
#include "FlareWeapon.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"


#define LOCTEXT_NAMESPACE "FlareBomb"


/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	TargetSpacecraft = NULL;

	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	// Settings
	PrimaryActorTick.bCanEverTick = true;
	Paused = false;
}


/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetParent()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectScale = WeaponDescription->WeaponCharacteristics.ExplosionEffectScale;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
		BombData.Identifier = Weapon->GetSpacecraft()->GetGame()->GenerateIdentifier(TEXT("bomb"));
	}

	SetActorEnableCollision(BombData.Activated);

	if (BombData.AttachTarget != NAME_None)
	{
		AFlareSpacecraft* AttachTarget = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AttachTarget);
		AttachBomb(AttachTarget);
	}
	if (BombData.AimTargetSpacecraft != NAME_None)
	{
		TargetSpacecraft = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AimTargetSpacecraft);
	}

	BombComp->BodyInstance.bUseCCD = true;

}

void AFlareBomb::OnLaunched(AFlareSpacecraft* Target)
{
	FLOG("AFlareBomb::OnLaunched");

	CombatLog::BombDropped(this);

	DetachRootComponentFromParent(true);
	ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->RegisterBomb(this);

	// Spin to stabilize
	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1, 0, 0));
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;
	BombData.BurnDuration = 0;
	TargetSpacecraft = Target;
}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	// Activate after few centimeters
	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance * 100)
		{
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
		LastTickRotation = GetActorRotation();
	}

	float ActivationTime = 2.0; // ins
	float MaxAcceleration = 5000; // in m.s-2
	float DirectionCorrectionThresold = 0.999; // In dot
	float NominalVelocity = 10000; // In cm/s
	float MaxBurnDuration = 30; // In s


	// Auto-destroy
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			// no fuel and 5 km and 30s auto-destroy
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (BombData.BurnDuration >= MaxBurnDuration && Distance > 500000 && BombData.LifeTime > 30)
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}

			// Parent removed destroy
			if (!ParentWeapon || !ParentWeapon->IsValidLowLevel() || !ParentWeapon->GetSpacecraft()->IsValidLowLevel())
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}
		}
	}

	float NeededAcceleration = 0;


	
	if (TargetSpacecraft && BombData.LifeTime > ActivationTime && BombData.BurnDuration < MaxBurnDuration)
	{
		//v2
		FVector TargetDeltaLocation = TargetSpacecraft->GetActorLocation() - GetActorLocation();
		FVector TargetDirection = TargetDeltaLocation.GetUnsafeNormal();


		FVector TargetVelocity = TargetSpacecraft->GetVelocity();

		FVector BombVelocityRefTarget = BombComp->GetPhysicsLinearVelocity() - TargetVelocity;
		FVector BombVelocityDirectionRefTarget = BombVelocityRefTarget.GetUnsafeNormal();


		FVector AimVelocityRefTarget = TargetDirection * NominalVelocity;


	
		float MaxDeltaV = MaxAcceleration * DeltaSeconds;

		float Dot = FVector::DotProduct(BombVelocityDirectionRefTarget, TargetDirection);
		FVector EffectiveDeltaVelocity;

		FVector FineAimVelocityRefTarget = AimVelocityRefTarget;


		/*FLOGV("TargetDeltaLocation %s", *TargetDeltaLocation.ToString());
		FLOGV("TargetDirection %s", *TargetDirection.ToString());
		FLOGV("TargetVelocity %s", *TargetVelocity.ToString());
		FLOGV("BombVelocityRefTarget %s", *BombVelocityRefTarget.ToString());
		FLOGV("BombVelocityDirectionRefTarget %s", *BombVelocityDirectionRefTarget.ToString());
		FLOGV("AimVelocityRefTarget %s", *AimVelocityRefTarget.ToString());<commit_msg>#628 Set bombs in pre physic tick<commit_after>
#include "../Flare.h"
#include "FlareSpacecraft.h"
#include "../Game/FlareAsteroid.h"
#include "../Game/FlareGame.h"
#include "../Player/FlarePlayerController.h"
#include "FlareWeapon.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"


#define LOCTEXT_NAMESPACE "FlareBomb"


/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	TargetSpacecraft = NULL;

	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	// Settings
	PrimaryActorTick.bCanEverTick = true;
	PrimaryActorTick.TickGroup = TG_PrePhysics;
	Paused = false;
}


/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetParent()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectScale = WeaponDescription->WeaponCharacteristics.ExplosionEffectScale;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
		BombData.Identifier = Weapon->GetSpacecraft()->GetGame()->GenerateIdentifier(TEXT("bomb"));
	}

	SetActorEnableCollision(BombData.Activated);

	if (BombData.AttachTarget != NAME_None)
	{
		AFlareSpacecraft* AttachTarget = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AttachTarget);
		AttachBomb(AttachTarget);
	}
	if (BombData.AimTargetSpacecraft != NAME_None)
	{
		TargetSpacecraft = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AimTargetSpacecraft);
	}

	BombComp->BodyInstance.bUseCCD = true;

}

void AFlareBomb::OnLaunched(AFlareSpacecraft* Target)
{
	FLOG("AFlareBomb::OnLaunched");

	CombatLog::BombDropped(this);

	DetachRootComponentFromParent(true);
	ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->RegisterBomb(this);

	// Spin to stabilize
	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1, 0, 0));
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;
	BombData.BurnDuration = 0;
	TargetSpacecraft = Target;
}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	// Activate after few centimeters
	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance * 100)
		{
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
		LastTickRotation = GetActorRotation();
	}

	float ActivationTime = 2.0; // ins
	float MaxAcceleration = 5000; // in m.s-2
	float DirectionCorrectionThresold = 0.999; // In dot
	float NominalVelocity = 10000; // In cm/s
	float MaxBurnDuration = 30; // In s


	// Auto-destroy
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			// no fuel and 5 km and 30s auto-destroy
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (BombData.BurnDuration >= MaxBurnDuration && Distance > 500000 && BombData.LifeTime > 30)
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}

			// Parent removed destroy
			if (!ParentWeapon || !ParentWeapon->IsValidLowLevel() || !ParentWeapon->GetSpacecraft()->IsValidLowLevel())
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}
		}
	}

	float NeededAcceleration = 0;


	
	if (TargetSpacecraft && BombData.LifeTime > ActivationTime && BombData.BurnDuration < MaxBurnDuration)
	{
		//v2
		FVector TargetDeltaLocation = TargetSpacecraft->GetActorLocation() - GetActorLocation();
		FVector TargetPredictedLocation = TargetSpacecraft->GetActorLocation();
		FVector TargetDeltaLocation = TargetPredictedLocation - GetActorLocation();
		FVector TargetDirection = TargetDeltaLocation.GetUnsafeNormal();


		FVector TargetVelocity = TargetSpacecraft->GetVelocity();

		FVector BombVelocityRefTarget = BombComp->GetPhysicsLinearVelocity() - TargetVelocity;
		FVector BombVelocityDirectionRefTarget = BombVelocityRefTarget.GetUnsafeNormal();


		FVector AimVelocityRefTarget = TargetDirection * NominalVelocity;


	
		float MaxDeltaV = MaxAcceleration * DeltaSeconds;

		float Dot = FVector::DotProduct(BombVelocityDirectionRefTarget, TargetDirection);
		FVector EffectiveDeltaVelocity;

		FVector FineAimVelocityRefTarget = AimVelocityRefTarget;


		/*FLOGV("TargetDeltaLocation %s", *TargetDeltaLocation.ToString());
		FLOGV("TargetDirection %s", *TargetDirection.ToString());
		FLOGV("TargetVelocity %s", *TargetVelocity.ToString());
		FLOGV("BombVelocityRefTarget %s", *BombVelocityRefTarget.ToString());
		FLOGV("BombVelocityDirectionRefTarget %s", *BombVelocityDirectionRefTarget.ToString());
		FLOGV("AimVelocityRefTarget %s", *AimVelocityRefTarget.ToString());
{'fraction_non_alphanumeric': 0.14966887417218544, 'fraction_numerical': 0.00880405142189326, 'mean_word_length': 4.986940298507463, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 122, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2000743', 'n_tokens_mistral': 4353, 'n_tokens_neox': 3962, 'n_words': 622}