presidents-brigade/Source/PresidentsBrigade/BasePawn.cpp
2022-11-12 14:33:50 -08:00

202 lines
4.6 KiB
C++
Executable File

// Fill out your copyright notice in the Description page of Project Settings.
#include "BasePawn.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/FloatingPawnMovement.h"
#include "Util.h"
#define LogInfo(Msg) Util::log_info(TEXT("ABasePawn"), Msg)
// Sets default values
ABasePawn::ABasePawn(const FObjectInitializer &object_initializer):
APawn(object_initializer)
{
// Create default components.
root_component = object_initializer.CreateDefaultSubobject<USceneComponent>(this, FName("Root"));
RootComponent = root_component;
collision = object_initializer.CreateDefaultSubobject<UBoxComponent>(this, FName("Collision"));
collision->SetupAttachment(RootComponent);
collision->SetCollisionProfileName(FName("Pawn"));
collision->SetCanEverAffectNavigation(false);
player_mesh = object_initializer.CreateDefaultSubobject<UStaticMeshComponent>(this, FName("PlayerMesh"));
player_mesh->SetupAttachment(collision);
player_mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
player_mesh->SetCanEverAffectNavigation(false);
movement_component = object_initializer.CreateDefaultSubobject<UFloatingPawnMovement>(this, FName("MovementComponent"));
movement_component->UpdatedComponent = collision;
PrimaryActorTick.bCanEverTick = true;
// Set defaults.
max_health = 100;
}
// Called when the game starts or when spawned
void ABasePawn::BeginPlay()
{
Super::BeginPlay();
/*
* Setup collision handler.
*/
collision->OnComponentHit.AddDynamic(this, &ABasePawn::handle_hit);
/*
* Set base state.
*/
current_health = max_health;
}
void ABasePawn::handle_hit(
UPrimitiveComponent* hit_component,
AActor* other_actor,
UPrimitiveComponent* other_component,
FVector normal_impulse,
const FHitResult& hit
)
{
UClass* other_class = other_actor->GetClass();
if (damage_class_map.Contains(other_class))
{
// Update current health.
current_health -= damage_class_map[other_class];
LogInfo(FString::Printf(TEXT("Total health %d"), current_health));
}
}
UPawnMovementComponent* ABasePawn::GetMovementComponent() const
{
return movement_component;
}
FVector ABasePawn::get_location() const
{
return collision->GetComponentLocation();
}
// Called every frame
void ABasePawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
/*
* Auto-fire.
*/
shoot_time_elapsed += DeltaTime;
if (shooting_enabled && shoot_time_elapsed > fire_rate_s)
{
shoot();
}
/*
* Handle death.
*/
if (current_health <= 0)
{
handle_death();
current_health = max_health;
}
}
void ABasePawn::handle_move_forward(float axis)
{
if (axis != 0)
{
AddMovementInput(FVector(1,0,0), axis);
}
}
void ABasePawn::handle_move_right(float axis)
{
if (axis != 0)
{
AddMovementInput(FVector(0, 1, 0), axis);
}
}
void ABasePawn::update_yaw_x(float x_component)
{
yaw.x_component = x_component;
}
void ABasePawn::update_yaw_y(float y_component)
{
yaw.y_component = y_component;
}
void ABasePawn::start_shooting()
{
shooting_enabled = true;
shoot();
}
void ABasePawn::stop_shooting()
{
shooting_enabled = false;
}
void ABasePawn::shoot()
{
FVector player_location = player_mesh->GetComponentLocation();
const float y = yaw.calculate_yaw();
LogInfo(FString::Printf(TEXT("Raw yaw: %f"), y));
const FRotator rotator(0, y, 0);
FVector forward = FRotationMatrix(rotator).GetUnitAxis(EAxis::X) * 100;
FVector spawn_location = player_location + forward;
FActorSpawnParameters spawnParameters;
spawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
spawnParameters.Owner = this;
spawnParameters.Instigator = this;
AActor* bullet = GetWorld()->SpawnActor<AActor>(
bullet_actor_class,
spawn_location,
rotator,
spawnParameters
);
shoot_time_elapsed = 0;
}
void ABasePawn::handle_death()
{
/*
* Disable collision.
*/
collision->SetCollisionEnabled(ECollisionEnabled::NoCollision);
if (death_effect)
{
death_effect->Destroy();
death_effect = nullptr;
}
/*
* Spawn particle effect.
*/
FVector player_location = player_mesh->GetComponentLocation();
FActorSpawnParameters spawnParameters;
spawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
death_effect = GetWorld()->SpawnActor<AActor>(
death_class,
player_location,
FRotator(0,0,0),
spawnParameters
);
destroy_self();
}
void ABasePawn::destroy_self()
{
/*
* Remove thyself from this world.
*/
Destroy();
}