Implement basic combat system

This commit is contained in:
2025-02-17 23:24:04 +05:30
parent 4b588e8667
commit 939e851c37
14 changed files with 293 additions and 112 deletions

View File

@@ -1,24 +1,33 @@
#include "EnemySpaceship.h"
#include "SpaceshipPawn.h"
#include "SpaceshipProjectile.h"
#include "Kismet/GameplayStatics.h"
AEnemySpaceship::AEnemySpaceship()
{
PrimaryActorTick.bCanEverTick = true;
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
RootComponent = ShipMesh;
// Create and setup the enemy mesh
EnemyMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("EnemyMesh"));
RootComponent = EnemyMesh;
CurrentHealth = MaxHealth;
// Disable gravity and physics simulation
EnemyMesh->SetSimulatePhysics(false);
EnemyMesh->SetEnableGravity(false);
// Set up collision for the enemy mesh
EnemyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
EnemyMesh->SetCollisionObjectType(ECC_Pawn);
EnemyMesh->SetCollisionResponseToAllChannels(ECR_Block);
EnemyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore); // Ignore other pawns
EnemyMesh->SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECR_Ignore); // Ignore player
EnemyMesh->SetGenerateOverlapEvents(true);
}
void AEnemySpaceship::BeginPlay()
{
Super::BeginPlay();
PlayerPawn = Cast<ASpaceshipPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
GetWorldTimerManager().SetTimer(FireTimerHandle, this, &AEnemySpaceship::FireAtPlayer, FireRate, true);
// Find the player pawn
PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
}
void AEnemySpaceship::Tick(float DeltaTime)
@@ -27,66 +36,43 @@ void AEnemySpaceship::Tick(float DeltaTime)
if (PlayerPawn)
{
// Calculate distance to player
float DistanceToPlayer = FVector::Dist(GetActorLocation(), PlayerPawn->GetActorLocation());
// Move towards the player
FVector Direction = (PlayerPawn->GetActorLocation() - GetActorLocation()).GetSafeNormal();
FVector NewLocation = GetActorLocation() + Direction * MovementSpeed * DeltaTime;
SetActorLocation(NewLocation);
if (DistanceToPlayer <= DetectionRange)
{
// Look at player
FVector Direction = PlayerPawn->GetActorLocation() - GetActorLocation();
FRotator NewRotation = Direction.Rotation();
SetActorRotation(FMath::RInterpTo(GetActorRotation(), NewRotation, DeltaTime, 2.0f));
// Move towards player while maintaining some distance
float TargetDistance = 1000.0f;
if (DistanceToPlayer > TargetDistance)
{
FVector NewLocation = GetActorLocation() + (Direction.GetSafeNormal() * MovementSpeed * DeltaTime);
SetActorLocation(NewLocation);
}
else if (DistanceToPlayer < TargetDistance - 100.0f)
{
FVector NewLocation = GetActorLocation() - (Direction.GetSafeNormal() * MovementSpeed * DeltaTime);
SetActorLocation(NewLocation);
}
}
// Face towards the player
FRotator NewRotation = Direction.Rotation();
SetActorRotation(NewRotation);
}
}
void AEnemySpaceship::FireAtPlayer()
{
if (PlayerPawn && FVector::Dist(GetActorLocation(), PlayerPawn->GetActorLocation()) <= DetectionRange)
{
UWorld* World = GetWorld();
if (World)
{
FVector SpawnLocation = GetActorLocation() + (GetActorForwardVector() * 100.0f);
FRotator SpawnRotation = GetActorRotation();
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = GetInstigator();
ASpaceshipProjectile* Projectile = World->SpawnActor<ASpaceshipProjectile>(
ASpaceshipProjectile::StaticClass(),
SpawnLocation,
SpawnRotation,
SpawnParams
);
}
}
}
float AEnemySpaceship::TakeDamage(float Damage, FDamageEvent const& DamageEvent,
float AEnemySpaceship::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent,
AController* EventInstigator, AActor* DamageCauser)
{
float ActualDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
float DamageToApply = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
CurrentHealth -= ActualDamage;
if (CurrentHealth <= 0)
CurrentHealth -= DamageToApply;
// Debug message
if (GEngine)
{
// Destroy the enemy ship
Destroy();
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red,
FString::Printf(TEXT("Enemy Health: %f"), CurrentHealth));
}
return ActualDamage;
if (CurrentHealth <= 0)
{
Die();
}
return DamageToApply;
}
void AEnemySpaceship::Die()
{
// Add any death effects here
// Destroy the enemy
Destroy();
}