// 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(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(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(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 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(actor); } } } if (!found) { // LogError("No president found!"); } return found; }