// Copyright Epic Games, Inc. All Rights Reserved. #include "Variant_Horror/HorrorCharacter.h" #include "Engine/World.h" #include "TimerManager.h" #include "GameFramework/CharacterMovementComponent.h" #include "Camera/CameraComponent.h" #include "Components/SpotLightComponent.h" #include "EnhancedInputComponent.h" #include "InputAction.h" AHorrorCharacter::AHorrorCharacter() { // create the spotlight SpotLight = CreateDefaultSubobject(TEXT("SpotLight")); SpotLight->SetupAttachment(GetFirstPersonCameraComponent()); SpotLight->SetRelativeLocationAndRotation(FVector(30.0f, 17.5f, -5.0f), FRotator(-18.6f, -1.3f, 5.26f)); SpotLight->Intensity = 0.5; SpotLight->SetIntensityUnits(ELightUnits::Lumens); SpotLight->AttenuationRadius = 1050.0f; SpotLight->InnerConeAngle = 18.7f; SpotLight->OuterConeAngle = 45.24f; } void AHorrorCharacter::BeginPlay() { Super::BeginPlay(); // initialize sprint meter to max SprintMeter = SprintTime; // Initialize the walk speed GetCharacterMovement()->MaxWalkSpeed = WalkSpeed; // start the sprint tick timer GetWorld()->GetTimerManager().SetTimer(SprintTimer, this, &AHorrorCharacter::SprintFixedTick, SprintFixedTickTime, true); } void AHorrorCharacter::EndPlay(EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); // clear the sprint timer GetWorld()->GetTimerManager().ClearTimer(SprintTimer); } void AHorrorCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); { // Set up action bindings if (UEnhancedInputComponent* EnhancedInputComponent = Cast(PlayerInputComponent)) { // Sprinting EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AHorrorCharacter::DoStartSprint); EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AHorrorCharacter::DoEndSprint); } } } void AHorrorCharacter::DoStartSprint() { // set the sprinting flag bSprinting = true; // are we out of recovery mode? if (!bRecovering) { // set the sprint walk speed GetCharacterMovement()->MaxWalkSpeed = SprintSpeed; // call the sprint state changed delegate OnSprintStateChanged.Broadcast(true); } } void AHorrorCharacter::DoEndSprint() { // set the sprinting flag bSprinting = false; // are we out of recovery mode? if (!bRecovering) { // set the default walk speed GetCharacterMovement()->MaxWalkSpeed = WalkSpeed; // call the sprint state changed delegate OnSprintStateChanged.Broadcast(false); } } void AHorrorCharacter::SprintFixedTick() { // are we out of recovery, still have stamina and are moving faster than our walk speed? if (bSprinting && !bRecovering && GetVelocity().Length() > WalkSpeed) { // do we still have meter to burn? if (SprintMeter > 0.0f) { // update the sprint meter SprintMeter = FMath::Max(SprintMeter - SprintFixedTickTime, 0.0f); // have we run out of stamina? if (SprintMeter <= 0.0f) { // raise the recovering flag bRecovering = true; // set the recovering walk speed GetCharacterMovement()->MaxWalkSpeed = RecoveringWalkSpeed; } } } else { // recover stamina SprintMeter = FMath::Min(SprintMeter + SprintFixedTickTime, SprintTime); if (SprintMeter >= SprintTime) { // lower the recovering flag bRecovering = false; // set the walk or sprint speed depending on whether the sprint button is down GetCharacterMovement()->MaxWalkSpeed = bSprinting ? SprintSpeed : WalkSpeed; // update the sprint state depending on whether the button is down or not OnSprintStateChanged.Broadcast(bSprinting); } } // broadcast the sprint meter updated delegate OnSprintMeterUpdated.Broadcast(SprintMeter / SprintTime); }