183 lines
4.8 KiB
C++
Executable File
183 lines
4.8 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"
|
|
|
|
#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();
|
|
LogInfo(FString::Printf(TEXT("Total ammo %d"), current_ammo));
|
|
}
|
|
}
|
|
|
|
void APlayerPawn::Tick(float delta_time)
|
|
{
|
|
Super::Tick(delta_time);
|
|
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)
|
|
{
|
|
LogError("Cannot boost! You're on cooldown");
|
|
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);
|
|
} |