presidents-brigade/Source/PresidentsBrigade/PlayerPawn.cpp
2022-11-17 01:40:04 -08:00

223 lines
5.4 KiB
C++
Executable File

// Fill out your copyright notice in the Description page of Project Settings.
#include "PlayerPawn.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/FloatingPawnMovement.h"
#include "Math/UnrealMathUtility.h"
#include "Util.h"
#include "EngineUtils.h"
#define LogInfo(Msg) Util::log_info(TEXT("APlayerPawn"), Msg)
#define LogError(Msg) Util::log_error(TEXT("APlayerPawn"), Msg)
APlayerPawn::APlayerPawn(const FObjectInitializer &object_initializer):
ABasePawn(object_initializer)
{
main_camera = object_initializer.CreateDefaultSubobject<UCameraComponent>(this, FName("MainCamera"));
main_camera->SetupAttachment(root_component);
boost_multiplier = 3.0f;
reset_threshold_s = .5f;
cooldown_threshold_s = 3.0f;
// You can boost right away.
cooldown_wait_s = cooldown_threshold_s + 1.0f;
reset_wait_s = reset_threshold_s + 1.0f;
}
// Called to bind functionality to input
void APlayerPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &ABasePawn::handle_move_forward);
PlayerInputComponent->BindAxis("MoveRight", this, &ABasePawn::handle_move_right);
PlayerInputComponent->BindAxis("YawXUpdate", this, &ABasePawn::update_yaw_x);
PlayerInputComponent->BindAxis("YawYUpdate", this, &ABasePawn::update_yaw_y);
PlayerInputComponent->BindAction("Shoot", EInputEvent::IE_Pressed, this, &ABasePawn::start_shooting);
PlayerInputComponent->BindAction("Shoot", EInputEvent::IE_Released, this, &ABasePawn::stop_shooting);
PlayerInputComponent->BindAction("Boost", EInputEvent::IE_Pressed, this, &APlayerPawn::boost);
PlayerInputComponent->BindAction("Boost", EInputEvent::IE_Released, this, &APlayerPawn::reset_boost);
}
void APlayerPawn::BeginPlay()
{
Super::BeginPlay();
/*
* Setup collision handler.
*/
collision->OnComponentBeginOverlap.AddDynamic(this, &APlayerPawn::handle_overlap);
}
void APlayerPawn::handle_overlap(
UPrimitiveComponent *overlapped_component,
AActor *other_actor,
UPrimitiveComponent *other_component,
int32 other_body_index,
bool from_sweep,
const FHitResult& hit)
{
UClass* other_class = other_actor->GetClass();
if (ammo_class_map.Contains(other_class))
{
// Update current ammo.
current_ammo += ammo_class_map[other_class];
if (current_ammo > max_ammo)
{
current_ammo = max_ammo;
}
other_actor->Destroy();
}
}
void APlayerPawn::Tick(float delta_time)
{
Super::Tick(delta_time);
if (!init)
{
president_ref = get_president();
init = true;
}
if (cooldown_wait_s < cooldown_threshold_s)
{
cooldown_wait_s += delta_time;
}
if (reset_wait_s < reset_threshold_s)
{
reset_wait_s += delta_time;
}
if (reset_wait_s >= reset_threshold_s)
{
reset_boost();
}
if (respawn_wait_s > 0)
{
respawn_wait_s -= delta_time;
if (respawn_wait_s <= 0)
{
respawn();
}
}
}
void APlayerPawn::boost()
{
const bool boost_allowed = cooldown_wait_s >= cooldown_threshold_s;
if (!boost_allowed)
{
return;
}
const float current_speed = movement_component->GetMaxSpeed();
const float current_accel = movement_component->Acceleration;
if (!default_max_speed || FMath::IsNearlyEqual(current_speed, default_max_speed, 0.001f))
{
default_max_speed = current_speed;
default_max_accel = current_accel;
movement_component->MaxSpeed = default_max_speed * boost_multiplier;
movement_component->Acceleration = default_max_accel * boost_multiplier;
reset_wait_s = 0;
}
}
void APlayerPawn::reset_boost()
{
if (!default_max_speed)
{
// We haven't boosted yet. Ignore.
return;
}
const float current_speed = movement_component->GetMaxSpeed();
const float current_accel = movement_component->Acceleration;
if (!FMath::IsNearlyEqual(current_speed, default_max_speed, 0.001f))
{
movement_component->MaxSpeed = default_max_speed;
movement_component->Acceleration = default_max_accel;
cooldown_wait_s = 0;
}
}
void APlayerPawn::destroy_self()
{
APlayerController* controller = Cast<APlayerController>(Controller);
if (!controller)
{
LogError("Cannot find palyer controller");
return;
}
stop_shooting();
reset_boost();
DisableInput(controller);
player_mesh->SetHiddenInGame(true);
if (death_effect)
{
death_effect->Destroy();
death_effect = nullptr;
}
/*
* Start respawn timer.
*/
respawn_wait_s = respawn_s;
}
void APlayerPawn::respawn()
{
APlayerController* controller = Cast<APlayerController>(Controller);
if (!controller)
{
LogError("Cannot find palyer controller");
return;
}
EnableInput(controller);
player_mesh->SetHiddenInGame(false);
collision->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
current_health = max_health;
death_handled = false;
}
/**
* Helper function to find president in level.
*/
ABasePawn* APlayerPawn::get_president() const
{
ABasePawn* found = nullptr;
for (TActorIterator<AActor> iterator(GetWorld()); iterator; ++iterator)
{
AActor* actor = *iterator;
if (actor && actor != this)
{
UClass* actor_class = actor->GetClass();
if (actor_class == (*president_class))
{
if (found)
{
LogError("Multiple presidents found!");
break;
}
found = Cast<ABasePawn>(actor);
}
}
}
if (!found)
{
// LogError("No president found!");
}
return found;
}