AzureAbyss/Source/the_twilight_abyss/TurnBasedCombatV2/TurnBaseCombatV2.cpp

480 lines
14 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "TurnBaseCombatV2.h"
#include "CoreMinimal.h"
#include "AIController.h"
#include "StatusSystem.h"
#include "Blueprint/UserWidget.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Components/TextBlock.h"
#include "Components/ProgressBar.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
#include "the_twilight_abyss/PlayerTemp/TempCharacter.h"
// Sets default values
ATurnBaseCombatV2::ATurnBaseCombatV2()
{
if (HUDWidget == nullptr)
{
static ConstructorHelpers::FClassFinder<UUserWidget> HUDWidgetClass(TEXT("/Game/Blueprints/Combat_UI/Combat_UI"));
HUDWidget = HUDWidgetClass.Class;
static ConstructorHelpers::FClassFinder<UStatusEffect> StatusEffectThornsClassFinder(TEXT("/Game/Blueprints/StatusEffects/BP_Thorns"));
ThornsStatusEffect = StatusEffectThornsClassFinder.Class;
static ConstructorHelpers::FClassFinder<UStatusEffect> StatusEffectDOTClassFinder(TEXT("/Game/Blueprints/StatusEffects/BP_DamageOverTime"));
DOTStatusEffect = StatusEffectDOTClassFinder.Class;
}
}
void ATurnBaseCombatV2::StartCombat(AActor* Enemy)
{
if (Enemy == nullptr) return;
UBlackboardComponent* EnemyBlackboard = Cast<AAIController>(Enemy->GetInstigatorController())->GetBlackboardComponent();
if (EnemyBlackboard->GetValueAsBool("IsInCombat")) return;
EnemyBlackboard->SetValueAsBool("IsInCombat", true);
FProperty* HealthProperty = Enemy->GetClass()->FindPropertyByName(FName("Health"));
int32* EnemyHealthPtr = HealthProperty->ContainerPtrToValuePtr<int32>(Enemy);
EnemyHealth = EnemyHealthPtr;
if (HUD->IsInViewport()) return;
HUD->AddToViewport();
EnemyActor = Enemy;
ProbertiumResource = 10;
EisResource = 10;
AzosResource = 10;
IroquoidResource = 10;
//Disable Character Movement
if (ACharacter* PlayerCharacter = Cast<ACharacter>(GetWorld()->GetFirstPlayerController()->GetPawn()))
{
PlayerCharacter->DisableInput(GetWorld()->GetFirstPlayerController());
}
//Set to UI Mode Only
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
PlayerController->SetInputMode(FInputModeUIOnly());
PlayerController->bShowMouseCursor = true;
FVector Direction = Enemy->GetActorLocation() - PlayerActor->GetActorLocation();
Direction.Normalize();
FRotator LookAtRotation = FRotationMatrix::MakeFromX(Direction).Rotator();
LookAtRotation.Pitch = -9.0f;
PlayerController->SetControlRotation(LookAtRotation);
//DrawDebugPoint(GetWorld(), Enemy->GetActorLocation(), 10, FColor::Red, false, 10);
CurrentComboString = "";
UpdateComboString(CurrentComboString);
RevertActionPoints();
UpdateActionPoints();
UpdateResourceBars();
ClearBattleLog();
}
void ATurnBaseCombatV2::EndCombat()
{
for (UStatusEffect* StatusEffect : StatusEffects)
{
StatusEffect->OnExpiry(PlayerActor);
}
HUD->RemoveFromParent();
APawn* PlayerPawn = Cast<APawn>(GetWorld()->GetFirstPlayerController()->GetPawn());
PlayerPawn->bUseControllerRotationYaw = true;
PlayerPawn->bUseControllerRotationPitch = true;
//Enable Character Movement
if (ACharacter* PlayerCharacter = Cast<ACharacter>(GetWorld()->GetFirstPlayerController()->GetPawn()))
{
PlayerCharacter->EnableInput(GetWorld()->GetFirstPlayerController());
}
//Set to Game Mode Only
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
PlayerController->SetInputMode(FInputModeGameOnly());
PlayerController->bShowMouseCursor = false;
}
// void ATurnBaseCombatV2::FKeyPressed()
// {
// PButtonOnClick();
// }
//
// void ATurnBaseCombatV2::WKeyPressed()
// {
// EButtonOnClick();
// }
void ATurnBaseCombatV2::BeginPlay()
{
Super::BeginPlay();
TArray<AActor*> AllCharacterActorsInScene;
UGameplayStatics::GetAllActorsOfClassWithTag(GetWorld(), AActor::StaticClass(), FName("Player"), AllCharacterActorsInScene);
for (AActor* Actor : AllCharacterActorsInScene)
{
PlayerActor = Cast<AActor>(Actor);
}
PlayerHealth = &Cast<ATempCharacter>(PlayerActor)->Health;
HUD = CreateWidget<UUserWidget>(GetWorld(), HUDWidget);
TurnIndicatorTextBlock = Cast<UTextBlock>(HUD->GetWidgetFromName("TurnIndicator"));
CurrentComboTextBlock = Cast<UTextBlock>(HUD->GetWidgetFromName("CurrentCombo"));
ActionPointsTextBlock = Cast<UTextBlock>(HUD->GetWidgetFromName("ActionPoints"));
BattleLogTextBlock = Cast<UTextBlock>(HUD->GetWidgetFromName("BattleLog"));
PlayerHealthBar = Cast<UProgressBar>(HUD->GetWidgetFromName("PlayerHealthBar"));
EnemyHealthBar = Cast<UProgressBar>(HUD->GetWidgetFromName("EnemyHealthBar"));
ProbertiumResourceBar = Cast<UProgressBar>(HUD->GetWidgetFromName("ProbertiumResourceBar"));
EisResourceBar = Cast<UProgressBar>(HUD->GetWidgetFromName("EisResourceBar"));
AzosResourceBar = Cast<UProgressBar>(HUD->GetWidgetFromName("AzosResourceBar"));
IroquoidResourceBar = Cast<UProgressBar>(HUD->GetWidgetFromName("IroquoidResourceBar"));
CastButton = Cast<UButton>(HUD->GetWidgetFromName("CastButton"));
PButton = Cast<UButton>(HUD->GetWidgetFromName("PButton"));
EButton = Cast<UButton>(HUD->GetWidgetFromName("EButton"));
AButton = Cast<UButton>(HUD->GetWidgetFromName("AButton"));
IButton = Cast<UButton>(HUD->GetWidgetFromName("IButton"));
BackspaceButton = Cast<UButton>(HUD->GetWidgetFromName("BackspaceButton"));
RunButton = Cast<UButton>(HUD->GetWidgetFromName("RunButton"));
CastButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::CastButtonOnClick);
PButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::PButtonOnClick);
EButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::EButtonOnClick);
AButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::AButtonOnClick);
IButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::IButtonOnClick);
BackspaceButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::BackspaceButtonOnClick);
RunButton->OnClicked.AddDynamic(this, &ATurnBaseCombatV2::RunButtonOnClick);
}
void ATurnBaseCombatV2::ExecuteCast(FString Combo)
{
if (!IsValidCombo(Combo))
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Invalid Combo"));
for (int i = 0; i < Combo.Len(); i++)
{
if (Combo[i] == 'P')
{
ProbertiumResource += 1;
}
else if (Combo[i] == 'E')
{
EisResource += 1;
}
else if (Combo[i] == 'A')
{
AzosResource += 1;
}
else if (Combo[i] == 'I')
{
IroquoidResource += 1;
}
}
CurrentComboString = "";
UpdateComboString(CurrentComboString);
RevertActionPoints();
UpdateActionPoints();
UpdateResourceBars();
return;
}
if (IsSpecialCombo(Combo))
{
UStatusSystem* StatusSystem = Cast<UStatusSystem>(PlayerActor->GetComponentByClass(UStatusSystem::StaticClass()));
if (Combo == "AAE")
{
UStatusEffect* TempThornsStatusEffect = NewObject<UStatusEffect>(PlayerActor, ThornsStatusEffect);
StatusSystem->AddStatusEffect(TempThornsStatusEffect, 1, false);
StatusEffects.Add(TempThornsStatusEffect);
AddBattleLogMessage("Player Casted Thorns");
}
else if (Combo == "PPI")
{
UStatusEffect* TempDOTStatusEffect = NewObject<UStatusEffect>(PlayerActor, DOTStatusEffect);
StatusSystem->AddStatusEffect(TempDOTStatusEffect, 1, false);
StatusEffects.Add(TempDOTStatusEffect);
AddBattleLogMessage("Player Casted DOT");
}
}
if (GunEffect)
{
const UStaticMeshComponent* GunComponent = Cast<UStaticMeshComponent>(PlayerActor->GetComponentsByTag(UPrimitiveComponent::StaticClass(), FName("Gun"))[0]);
const FVector GunLocationOffset = GunComponent->GetSocketTransform("Muzzle").TransformPosition(FVector(-100, 0, 0));
UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(), GunEffect, GunLocationOffset, PlayerActor->GetActorRotation());
}
CurrentComboString = "";
UpdateComboString(CurrentComboString);
RevertActionPoints();
UpdateActionPoints();
//Damage Calculation
switch (bIsPlayerTurn)
{
case true:
// Player Turn
DamageEnemy(*ValidCombos.Find(Combo));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Enemy Damaged %d"), *ValidCombos.Find(Combo)));
OnPlayerTurn.Broadcast(PlayerActor, EnemyActor);
break;
case false:
// Enemy Turn
DamagePlayer(*ValidCombos.Find(Combo));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Player Damaged %d"), *ValidCombos.Find(Combo)));
OnEnemyTurn.Broadcast(EnemyActor, PlayerActor);
break;
}
//Ends Combat if either the player or enemy is dead
if (*EnemyHealth <= 0)
{
EndCombat();
EnemyActor->Destroy();
return;
}
if (*PlayerHealth <= 0)
{
EndCombat();
return;
}
SwitchTurn();
}
void ATurnBaseCombatV2::UseActionPoint()
{
ActiveActionPoints += 1;
UpdateActionPoints();
}
void ATurnBaseCombatV2::ReuseActionPoint()
{
ActiveActionPoints -= 1;
UpdateActionPoints();
}
void ATurnBaseCombatV2::RevertActionPoints()
{
ActiveActionPoints = 0;
UpdateActionPoints();
}
void ATurnBaseCombatV2::DamagePlayer(int Damage, FString DamageType)
{
*PlayerHealth -= FMath::Clamp(Damage, 0, 100);
UpdateProgressBars();
AddBattleLogMessage("Player was damaged for " + FString::FromInt(Damage) + " HP by " + DamageType + ".");
}
void ATurnBaseCombatV2::DamageEnemy(int Damage, FString DamageType)
{
*EnemyHealth -= FMath::Clamp(Damage, 0, 100);
UpdateProgressBars();
AddBattleLogMessage("Enemy was damaged for " + FString::FromInt(Damage) + " HP by " + DamageType + ".");
}
void ATurnBaseCombatV2::UpdateProgressBars() const
{
PlayerHealthBar->SetPercent(*PlayerHealth / 100.0f);
EnemyHealthBar->SetPercent(*EnemyHealth / 100.0f);
}
bool ATurnBaseCombatV2::IsValidCombo(const FString Combo) const
{
return ValidCombos.Contains(Combo);
}
bool ATurnBaseCombatV2::IsSpecialCombo(const FString Combo) const
{
return SpecialCombos.Contains(Combo);
}
void ATurnBaseCombatV2::SwitchTurn()
{
//TurnIndicatorTextBlock->SetText(FText::FromString(bIsPlayerTurn ? "Enemy Turn" : "Player Turn"));
//bIsPlayerTurn = !bIsPlayerTurn;
TurnIndicatorTextBlock->SetText(FText::FromString("Enemy Turn"));
ToggleButtons();
FTimerHandle UnusedHandle;
GetWorldTimerManager().SetTimer(UnusedHandle, this, &ATurnBaseCombatV2::EnemyTurn, 2.0f, false);
//activeActor = bIsPlayerTurn ? enemyActor : playerActor;
}
void ATurnBaseCombatV2::CastButtonOnClick()
{
ExecuteCast(CurrentComboString);
}
void ATurnBaseCombatV2::PButtonOnClick()
{
if (ActiveActionPoints >= DefaultActionPoints)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Action Points"));
return;
}
if (ProbertiumResource <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Probertium"));
return;
}
UseActionPoint();
CurrentComboString.AppendChar('P');
UpdateComboString(CurrentComboString);
ProbertiumResource -= 1;
UpdateResourceBars();
}
void ATurnBaseCombatV2::EButtonOnClick()
{
if (ActiveActionPoints >= DefaultActionPoints)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Action Points"));
return;
}
if (EisResource <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Eis"));
return;
}
UseActionPoint();
CurrentComboString.AppendChar('E');
UpdateComboString(CurrentComboString);
EisResource -= 1;
UpdateResourceBars();
}
void ATurnBaseCombatV2::AButtonOnClick()
{
if (ActiveActionPoints >= DefaultActionPoints)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Action Points"));
return;
}
if (AzosResource <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Azos"));
return;
}
UseActionPoint();
CurrentComboString.AppendChar('A');
UpdateComboString(CurrentComboString);
AzosResource -= 1;
UpdateResourceBars();
}
void ATurnBaseCombatV2::IButtonOnClick()
{
if (ActiveActionPoints >= DefaultActionPoints)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Action Points"));
return;
}
if (IroquoidResource <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No More Iroquoid"));
return;
}
UseActionPoint();
CurrentComboString.AppendChar('I');
UpdateComboString(CurrentComboString);
IroquoidResource -= 1;
UpdateResourceBars();
}
void ATurnBaseCombatV2::BackspaceButtonOnClick()
{
if (CurrentComboString.Len() <= 0)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Blank Combo"));
return;
}
ReuseActionPoint();
if (CurrentComboString.Right(1) == "P")
{
ProbertiumResource += 1;
}
else if (CurrentComboString.Right(1) == "E")
{
EisResource += 1;
}
else if (CurrentComboString.Right(1) == "A")
{
AzosResource += 1;
}
else if (CurrentComboString.Right(1) == "I")
{
IroquoidResource += 1;
}
CurrentComboString.RemoveAt(CurrentComboString.Len() - 1);
UpdateComboString(CurrentComboString);
UpdateResourceBars();
}
void ATurnBaseCombatV2::RunButtonOnClick()
{
UBlackboardComponent* EnemyBlackboard = Cast<AAIController>(EnemyActor->GetInstigatorController())->GetBlackboardComponent();
EnemyBlackboard->SetValueAsBool("IsInCombat", false);
EndCombat();
}
void ATurnBaseCombatV2::UpdateComboString(FString NewCombo) const
{
CurrentComboTextBlock->SetText(FText::FromString(NewCombo));
}
void ATurnBaseCombatV2::UpdateActionPoints() const
{
ActionPointsTextBlock->SetText(FText::FromString(FString::FromInt(DefaultActionPoints - ActiveActionPoints)));
}
void ATurnBaseCombatV2::AddBattleLogMessage(FString Message)
{
BattleLog.Append(Message + "\n");
UpdateBattleLog();
}
void ATurnBaseCombatV2::ClearBattleLog()
{
BattleLog = "";
}
void ATurnBaseCombatV2::UpdateBattleLog()
{
TArray<FString> TempArray;
if (const int32 LineCount = BattleLog.ParseIntoArray(TempArray, TEXT("\n"), true); LineCount > 10)
{
ClearBattleLog();
}
BattleLogTextBlock->SetText(FText::FromString(BattleLog));
}
void ATurnBaseCombatV2::UpdateResourceBars() const
{
ProbertiumResourceBar->SetPercent(ProbertiumResource / 10.0f);
EisResourceBar->SetPercent(EisResource / 10.0f);
AzosResourceBar->SetPercent(AzosResource / 10.0f);
IroquoidResourceBar->SetPercent(IroquoidResource / 10.0f);
}
void ATurnBaseCombatV2::ToggleButtons() const
{
PButton->SetIsEnabled(!PButton->GetIsEnabled());
EButton->SetIsEnabled(!EButton->GetIsEnabled());
AButton->SetIsEnabled(!AButton->GetIsEnabled());
IButton->SetIsEnabled(!IButton->GetIsEnabled());
BackspaceButton->SetIsEnabled(!BackspaceButton->GetIsEnabled());
CastButton->SetIsEnabled(!CastButton->GetIsEnabled());
RunButton->SetIsEnabled(!RunButton->GetIsEnabled());
}
void ATurnBaseCombatV2::EnemyTurn()
{
DamagePlayer(10);
OnEnemyTurn.Broadcast(EnemyActor, PlayerActor);
TurnIndicatorTextBlock->SetText(FText::FromString("Player Turn"));
ToggleButtons();
}