MrGerwant

FightEncounter

Jan 1st, 2025 (edited)
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 39.12 KB | Source Code | 0 0
  1. // Fight.h
  2.  
  3. #pragma once
  4.  
  5. #include "CoreMinimal.h"
  6. #include "UObject/NoExportTypes.h"
  7. #include "Fight.generated.h"
  8.  
  9. class ACombatCharacter;
  10. class AAlly;
  11. class AEnemy;
  12. class AFightEncounter;
  13. class ADefaultHUD;
  14. class ADefaultGameMode;
  15. class USkill;
  16. class USummonSkill;
  17. class UItem;
  18. class APlayerController;
  19.  
  20. UCLASS()
  21. class WIRSPRAWIEDLIWOSCI_API UFight : public UObject
  22. {
  23.     GENERATED_BODY()
  24. public:
  25.     UFight();
  26.     void BuildTurnOrder();
  27.  
  28.     UFUNCTION()
  29.     void StartTurn();
  30.  
  31.     UFUNCTION()
  32.     void EndTurn();
  33.  
  34.     void MarkTargetsForSelection();
  35.     void MarkAllyTargetsForSelection();
  36.     void MarkEnemyTargetsForSelection();
  37.     bool SkillTargetsAlly();
  38.     bool SkillTargetsEnemy();
  39.     void AddCurrentCharacterToOverlay();
  40.     void AddSkillIconClickedEvents();
  41.     void AddItemClickedEvents();
  42.     void PerformEnemyTurn();
  43.     void ChooseAttackTarget();
  44.     AAlly* GetFirstAliveAlly();
  45.     bool NoTargetsForEnemyAttack();
  46.     void TriggerMelee(ACombatCharacter* Source);
  47.     void UseSkillMelee();
  48.     void CharacterMoveToLocation();
  49.     void ClearEnemyArrows();
  50.     AEnemy* GetLowestHealthEnemy();
  51.     AAlly* GetDefenderAlly();
  52.     AEnemy* GetDefenderEnemy();
  53.     AAlly* GetSpecificTarget();
  54.     USkill* GetEnemyHealingSkill(AEnemy* CurrentEnemy);
  55.     USkill* GetEnemySupportSkill(AEnemy* CurrentEnemy);
  56.     USkill* GetEnemySummonSkill(AEnemy* CurrentEnemy);
  57.     TArray<USkill*> GetEnemyAttacks(AEnemy* CurrentEnemy);
  58.     TArray<ACombatCharacter*> BuildTargetArray();
  59.     TArray<int32> GetAvailableAllyRanks();
  60.    
  61.     UFUNCTION()
  62.     void HandleOnSkillIconClicked(USkill* ClickedSkill);
  63.  
  64.     UFUNCTION()
  65.     void HandleOnEndTurnButtonClicked();
  66.  
  67.     UFUNCTION()
  68.     void HandleOnCharacterHover(ACombatCharacter* HoveredCharacter);
  69.  
  70.     UFUNCTION()
  71.     void HandleOnCharacterEndHover(ACombatCharacter* HoveredCharacter);
  72.  
  73.     UFUNCTION()
  74.     void HandleOnCharacterClicked(ACombatCharacter* ClickedCharacter);
  75.  
  76.     void UseSkill();
  77.  
  78.     void UseSummonSkill(USummonSkill* Skill);
  79.  
  80.     UFUNCTION()
  81.     void UseItem(UItem* Item);
  82.  
  83.     UFUNCTION()
  84.     void HandleOnTargetReached(ACombatCharacter* Character);
  85.  
  86.     UFUNCTION()
  87.     void HandleOnLocationReached(ACombatCharacter* Character);
  88.  
  89.     UFUNCTION()
  90.     void HandleOnCharacterDeath(ACombatCharacter* DeadCharacter);
  91.  
  92.     void EnableMouseEvents();
  93.     void DisableMouseEvents();
  94.  
  95.     inline static bool IsFaster(ACombatCharacter* A, ACombatCharacter* B);
  96.  
  97.     UPROPERTY()
  98.     APlayerController* Controller;
  99.  
  100.     UPROPERTY()
  101.     ADefaultGameMode* CurrentGameMode;
  102.  
  103.     UPROPERTY()
  104.     ACombatCharacter* CurrentCharacter;
  105.  
  106.     UPROPERTY()
  107.     ACombatCharacter* CurrentTarget;
  108.  
  109.     UPROPERTY()
  110.     TArray<ACombatCharacter*> Targets;
  111.  
  112.     UPROPERTY()
  113.     USkill* CurrentSkill;
  114.  
  115.     UPROPERTY()
  116.     TArray<AAlly*> AlliedParty;
  117.  
  118.     UPROPERTY()
  119.     TArray<AEnemy*> EnemyParty;
  120.  
  121.     UPROPERTY()
  122.     AFightEncounter* Encounter;
  123.  
  124.     UPROPERTY()
  125.     int16 AlliesAlive;
  126.  
  127.     UPROPERTY()
  128.     int16 EnemiesAlive;
  129.  
  130.     UPROPERTY()
  131.     ADefaultHUD* CurrentHUD;
  132.  
  133.     TQueue<ACombatCharacter*> TurnQueue;
  134.  
  135.     UPROPERTY()
  136.     FTimerHandle TurnTimer;
  137. };
  138.  
  139. //Fight.cpp
  140.  
  141. // Fill out your copyright notice in the Description page of Project Settings.
  142.  
  143.  
  144. #include "GameMechanics/Combat/Fight.h"
  145. #include "GameMechanics/Combat/FightEncounter.h"
  146. #include "GameMechanics/Skill.h"
  147. #include "GameMechanics/SummonSkill.h"
  148. #include "Characters/CombatCharacter.h"
  149. #include "Characters/Ally.h"
  150. #include "Characters/Enemy.h"
  151. #include "GameMechanics/AttributeComponent.h"
  152. #include "GameMechanics/Effect.h"
  153. #include "GameMechanics/GameModes/DefaultGameMode.h"
  154. #include "UI/DefaultHUD.h"
  155. #include "UI/InventorySlot.h"
  156. #include "UI/InventoryWidget.h"
  157. #include "UI/CombatOverlay.h"
  158. #include "UI/SkillIcon.h"
  159. #include "Items/Item.h"
  160. #include "Kismet/KismetStringLibrary.h"
  161.  
  162. UFight::UFight()
  163. {
  164. }
  165.  
  166. void UFight::BuildTurnOrder()
  167. {
  168.     TurnQueue.Empty();
  169.     TArray<ACombatCharacter*> BothParties;
  170.     BothParties.Append(AlliedParty);
  171.     BothParties.Append(EnemyParty);
  172.     Algo::Sort(BothParties, UFight::IsFaster);
  173.     for (ACombatCharacter* Character : BothParties)
  174.     {
  175.         TurnQueue.Enqueue(Character);
  176.         UE_LOG(LogTemp, Log, TEXT("Added character to TurnQueue: %s"), *Character->GetName());
  177.     }
  178.     BothParties.Empty();
  179. }
  180.  
  181. void UFight::StartTurn()
  182. {
  183.     CurrentSkill = nullptr;
  184.     CurrentCharacter = nullptr;
  185.     Targets.Empty();
  186.     TurnQueue.Dequeue(CurrentCharacter);
  187.     if (TurnQueue.IsEmpty())
  188.     {
  189.         BuildTurnOrder();
  190.     }
  191.     AddCurrentCharacterToOverlay();
  192.     if(!CurrentCharacter || !CurrentCharacter->IsValidLowLevel())
  193.     {
  194.         UE_LOG(LogTemp, Warning, TEXT("Invalid CurrentCharacter in StartTurn"));
  195.         EndTurn();
  196.         return;
  197.     }
  198.     CurrentCharacter->SetArrowToWhite();
  199.     CurrentCharacter->ShowArrow();
  200.     CurrentCharacter->StartTurn();
  201.     if (CurrentCharacter->ActorHasTag(FName("Stunned")))
  202.     {
  203.         CurrentCharacter->ReturnFromStun();
  204.         EndTurn();
  205.         return;
  206.     }
  207.     if (CurrentCharacter->ActorHasTag(FName("Dead")))
  208.     {
  209.         EndTurn();
  210.         return;
  211.     }
  212.     if (CurrentCharacter->IsA(AEnemy::StaticClass()))
  213.     {
  214.         CurrentCharacter->GetWorldTimerManager().SetTimer(TurnTimer, this, &UFight::PerformEnemyTurn, 2.f);
  215.     }
  216. }
  217.  
  218. void UFight::EndTurn()
  219. {
  220.     if(CurrentCharacter) CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  221.     DisableMouseEvents();
  222.     if (TurnQueue.IsEmpty())
  223.     {
  224.         BuildTurnOrder();
  225.     }
  226.     float TimeToWait = 0.5f;
  227.     if (CurrentSkill)
  228.     {
  229.         TimeToWait = CurrentSkill->AnimDuration + 0.3f;
  230.     }
  231.     if (CurrentHUD && CurrentHUD->CombatOverlay)
  232.     {
  233.         CurrentHUD->CombatOverlay->SetNewAlly(nullptr);
  234.     }
  235.     if (CurrentCharacter)
  236.     {
  237.         CurrentCharacter->UpdateEffectIcons();
  238.         CurrentCharacter->GetWorldTimerManager().SetTimer(CurrentCharacter->TurnTimer, CurrentCharacter, &ACombatCharacter::EndTurn, TimeToWait);
  239.         CurrentCharacter->GetWorldTimerManager().SetTimer(TurnTimer, this, &UFight::StartTurn, TimeToWait + 0.2);
  240.         CurrentCharacter->HideArrow();
  241.     }
  242. }
  243.  
  244. void UFight::MarkTargetsForSelection()
  245. {
  246.     MarkAllyTargetsForSelection();
  247.     MarkEnemyTargetsForSelection();
  248. }
  249.  
  250. void UFight::MarkAllyTargetsForSelection()
  251. {
  252.     bool bSkillHasSpecificTarget = false;
  253.     AAlly* SpecificTarget = GetSpecificTarget();
  254.     if (SpecificTarget)
  255.     {
  256.         bSkillHasSpecificTarget = true;
  257.     }
  258.     for (int i = 0; i < AlliedParty.Num(); i++)
  259.     {
  260.         if (SkillTargetsAlly() && CurrentSkill->ValidFirstTargetRanks.Contains(i + 1) && !AlliedParty[i]->ActorHasTag(FName("Dead")))
  261.         {
  262.             if (bSkillHasSpecificTarget && SpecificTarget->CharacterName != AlliedParty[i]->CharacterName)
  263.             {
  264.                 AlliedParty[i]->bSelectable = false;
  265.             }
  266.             else
  267.             {
  268.                 AlliedParty[i]->bSelectable = true;
  269.             }
  270.         }
  271.         else
  272.         {
  273.             AlliedParty[i]->bSelectable = false;
  274.         }
  275.     }
  276. }
  277.  
  278. void UFight::MarkEnemyTargetsForSelection()
  279. {
  280.     AEnemy* EnemyDefender = GetDefenderEnemy();
  281.     if (EnemyDefender)
  282.     {
  283.         for (int i = 0; i < EnemyParty.Num(); i++)
  284.         {
  285.             EnemyParty[i]->bSelectable = false;
  286.         }
  287.         EnemyDefender->bSelectable = true;
  288.         return;
  289.     }
  290.     for (int i = 0; i < EnemyParty.Num(); i++)
  291.     {
  292.         if (SkillTargetsEnemy() && CurrentSkill->ValidFirstTargetRanks.Contains(EnemyParty[i]->Rank))
  293.         {
  294.             EnemyParty[i]->bSelectable = true;
  295.         }
  296.         else
  297.         {
  298.             EnemyParty[i]->bSelectable = false;
  299.         }
  300.     }
  301. }
  302.  
  303. bool UFight::SkillTargetsAlly()
  304. {
  305.     return CurrentSkill->SkillType == ESkillType::EST_Heal || CurrentSkill->SkillType == ESkillType::EST_Support || CurrentSkill->SkillType == ESkillType::EST_AttackAlly
  306.         || CurrentSkill->SkillType == ESkillType::EST_UltSupport;
  307. }
  308.  
  309. bool UFight::SkillTargetsEnemy()
  310. {
  311.     return CurrentSkill->SkillType == ESkillType::EST_Attack || CurrentSkill->SkillType == ESkillType::EST_UltAttack;
  312. }
  313.  
  314. void UFight::AddCurrentCharacterToOverlay()
  315. {
  316.     if (TurnQueue.IsEmpty()) return;
  317.     if (!CurrentCharacter->IsValidLowLevel()) return;
  318.     CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  319.     if (CurrentHUD && CurrentHUD->CombatOverlay)
  320.     {
  321.         AAlly* CurrentAlly = Cast<AAlly>(CurrentCharacter);
  322.         if (CurrentAlly->IsValidLowLevel())
  323.         {
  324.             CurrentHUD->CombatOverlay->SetNewAlly(CurrentAlly);
  325.             AddSkillIconClickedEvents();
  326.         }
  327.         AEnemy* CurrentEnemy = Cast<AEnemy>(CurrentCharacter);
  328.         if (CurrentEnemy->IsValidLowLevel())
  329.         {
  330.             CurrentHUD->CombatOverlay->SetNewEnemy(CurrentEnemy);
  331.         }
  332.     }
  333. }
  334.  
  335. void UFight::AddSkillIconClickedEvents()
  336. {
  337.     CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  338.     if (!CurrentHUD) return;
  339.     TArray<USkillIcon*> SkillIcons = CurrentHUD->CombatOverlay->GetAllySkillIconsAsArray();
  340.     for (USkillIcon* SkillIcon : SkillIcons)
  341.     {
  342.         if (SkillIcon && SkillIcon->Skill)
  343.         {
  344.             SkillIcon->OnSkillIconClicked.AddUniqueDynamic(this, &UFight::HandleOnSkillIconClicked);
  345.         }
  346.     }
  347.     CurrentHUD->CombatOverlay->AllyUlt->OnSkillIconClicked.AddUniqueDynamic(this, &UFight::HandleOnSkillIconClicked);
  348. }
  349.  
  350. void UFight::AddItemClickedEvents()
  351. {
  352.     if (!CurrentHUD) return;
  353.     for (UInventorySlot* ItemSlot : CurrentHUD->InventoryWidget->InventorySlots)
  354.     {
  355.         ItemSlot->OnItemClicked.AddUniqueDynamic(this, &UFight::UseItem);
  356.     }
  357. }
  358.  
  359. void UFight::PerformEnemyTurn()
  360. {
  361.     AEnemy* CurrentEnemy = Cast<AEnemy>(CurrentCharacter);
  362.     CurrentCharacter->GetWorldTimerManager().SetTimer(TurnTimer, this, &UFight::EndTurn, 15.f);
  363.     if (CurrentEnemy)
  364.     {
  365.         USkill* SummonSkill = GetEnemySummonSkill(CurrentEnemy);
  366.         if (SummonSkill && CurrentEnemy->Attributes->GetHealthPercent() <= 0.4 && EnemyParty.Num()<=3)
  367.         {
  368.             CurrentTarget = CurrentEnemy;
  369.             CurrentSkill = SummonSkill;
  370.             Targets = BuildTargetArray();
  371.             CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  372.             UseSkill();
  373.             EndTurn();
  374.         }
  375.         AEnemy* LowestHealthEnemy = GetLowestHealthEnemy();
  376.         USkill* HealingSkill = GetEnemyHealingSkill(CurrentEnemy);
  377.         if (LowestHealthEnemy->Attributes->GetHealthPercent()<=0.35f && HealingSkill)
  378.         {
  379.             CurrentTarget = LowestHealthEnemy;
  380.             CurrentSkill = HealingSkill;
  381.             Targets = BuildTargetArray();
  382.             if (CurrentSkill->bMelee)
  383.             {
  384.                 TriggerMelee(CurrentEnemy);
  385.             }
  386.             else
  387.             {
  388.                 CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  389.                 UseSkill();
  390.                 EndTurn();
  391.             }
  392.             return;
  393.         }
  394.         USkill* SupportSkill = GetEnemySupportSkill(CurrentEnemy);
  395.         if (CurrentEnemy->Turn<=3 && !CurrentEnemy->bHasBuffs() && SupportSkill &&
  396.             !(SupportSkill->GetInflictedEffect() && SupportSkill->GetInflictedEffect()->bHeal
  397.                 && LowestHealthEnemy->Attributes->GetHealth() == LowestHealthEnemy->Attributes->GetMaxHealth()))
  398.         {
  399.             CurrentSkill = SupportSkill;
  400.             int32 Rank =
  401.                 CurrentSkill->ValidFirstTargetRanks.IsEmpty() ? EnemyParty.Find(CurrentEnemy)+1 :
  402.                 FMath::RandRange(CurrentSkill->ValidFirstTargetRanks[0], CurrentSkill->ValidFirstTargetRanks[CurrentSkill->ValidFirstTargetRanks.Num() - 1]);
  403.             if ((Rank - 1) < EnemyParty.Num())
  404.             {
  405.                 CurrentTarget = EnemyParty[Rank - 1];
  406.             }
  407.             Targets = BuildTargetArray();
  408.             if (CurrentSkill->bMelee)
  409.             {
  410.                 TriggerMelee(CurrentEnemy);
  411.             }
  412.             else
  413.             {
  414.                 CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  415.                 UseSkill();
  416.                 EndTurn();
  417.             }
  418.             return;
  419.         }
  420.         TArray<USkill*> EnemyAttacks = GetEnemyAttacks(CurrentEnemy);
  421.         if (!EnemyAttacks.IsEmpty())
  422.         {
  423.             int32 Index = FMath::RandRange(0, EnemyAttacks.Num() - 1);
  424.             CurrentSkill = EnemyAttacks[Index];
  425.             ChooseAttackTarget();
  426.             UEffect* InflictedEffect = CurrentSkill->GetInflictedEffect();
  427.             if (InflictedEffect)
  428.             {
  429.                 UEffect* EffectOfType = CurrentTarget->GetEffectOfType(InflictedEffect->EffectType);
  430.                 if (EffectOfType && EffectOfType->GetDuration() >= 2)
  431.                 {
  432.                     EnemyAttacks.Remove(CurrentSkill);
  433.                     if (EnemyAttacks.IsEmpty())
  434.                     {
  435.                         EndTurn();
  436.                         return;
  437.                     }
  438.                     Index = FMath::RandRange(0, EnemyAttacks.Num() - 1);
  439.                     CurrentSkill = EnemyAttacks[Index];
  440.                     ChooseAttackTarget();
  441.                 }
  442.             }
  443.             if (NoTargetsForEnemyAttack())
  444.             {
  445.                 EnemyAttacks.Remove(CurrentSkill);
  446.                 if (EnemyAttacks.IsEmpty())
  447.                 {
  448.                     EndTurn();
  449.                     return;
  450.                 }
  451.                 Index = FMath::RandRange(0, EnemyAttacks.Num() - 1);
  452.                 CurrentSkill = EnemyAttacks[Index];
  453.                 if (NoTargetsForEnemyAttack())
  454.                 {
  455.                     EndTurn();
  456.                     return;
  457.                 }
  458.                 ChooseAttackTarget();
  459.             }
  460.             Targets = BuildTargetArray();
  461.             if (CurrentSkill->bMelee)
  462.             {
  463.                 TriggerMelee(CurrentEnemy);
  464.             }
  465.             else
  466.             {
  467.                 CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  468.                 UseSkill();
  469.                 EndTurn();
  470.             }
  471.             return;
  472.         }
  473.     }
  474.     else
  475.     {
  476.         CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  477.         EndTurn();
  478.         return;
  479.     }
  480. }
  481.  
  482. void UFight::ChooseAttackTarget()
  483. {
  484.     AAlly* AllyDefender = GetDefenderAlly();
  485.     if (AllyDefender)
  486.     {
  487.         CurrentTarget = AllyDefender;
  488.         return;
  489.     }
  490.     if (NoTargetsForEnemyAttack())
  491.     {
  492.         EndTurn();
  493.         return;
  494.     }
  495.     TArray<int32> AvailableAllyRanks = GetAvailableAllyRanks();
  496.     if (AvailableAllyRanks.IsEmpty())
  497.     {
  498.         EndTurn();
  499.         return;
  500.     }
  501.     else
  502.     {
  503.         int32 Index = FMath::RandRange(0, AvailableAllyRanks.Num() - 1);
  504.         if (AvailableAllyRanks[Index] < AlliedParty.Num() && AlliedParty[AvailableAllyRanks[Index]])
  505.         {
  506.             CurrentTarget = AlliedParty[AvailableAllyRanks[Index]];
  507.         }
  508.         else
  509.         {
  510.             ChooseAttackTarget();
  511.         }
  512.     }
  513. }
  514.  
  515. AAlly* UFight::GetFirstAliveAlly()
  516. {
  517.     for (AAlly* Ally : AlliedParty)
  518.     {
  519.         if (Ally->ActorHasTag(FName("Dead")))
  520.         {
  521.             return Ally;
  522.         }
  523.     }
  524.     return nullptr;
  525. }
  526.  
  527. bool UFight::NoTargetsForEnemyAttack()
  528. {
  529.     for (AAlly* Ally : AlliedParty)
  530.     {
  531.         if (CurrentSkill && CurrentSkill->ValidFirstTargetRanks.Contains(AlliedParty.Find(Ally)) && !Ally->ActorHasTag(FName("Dead")))
  532.         {
  533.             return false;
  534.         }
  535.     }
  536.     return true;
  537. }
  538.  
  539. void UFight::TriggerMelee(ACombatCharacter* Source)
  540. {
  541.     if (Targets.IsEmpty())
  542.     {
  543.         EndTurn();
  544.         return;
  545.     }
  546.     if(Targets[0] != Source)
  547.     {
  548.         Source->CombatTarget = Targets[0];
  549.         Source->TargetLocation = Source->InitialLocation;
  550.         Source->bShouldMoveToTarget = true;
  551.     }
  552.     else
  553.     {
  554.         CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  555.         UseSkill();
  556.         EndTurn();
  557.         return;
  558.     }
  559. }
  560.  
  561. AEnemy* UFight::GetLowestHealthEnemy()
  562. {
  563.     if (EnemyParty.IsEmpty()) return nullptr;
  564.     AEnemy* LowestHealthEnemy = EnemyParty[0];
  565.     for (int i = 1; i < EnemyParty.Num(); i++)
  566.     {
  567.         if (i < EnemyParty.Num() && EnemyParty[i] && EnemyParty[i]->Attributes->GetHealth() < EnemyParty[i - 1]->Attributes->GetHealth())
  568.         {
  569.             LowestHealthEnemy = EnemyParty[i];
  570.         }
  571.     }
  572.     return LowestHealthEnemy;
  573. }
  574.  
  575. AAlly* UFight::GetDefenderAlly()
  576. {
  577.     if (AlliedParty.IsEmpty())
  578.     {
  579.         return nullptr;
  580.     }
  581.     for (int i = 0; i < AlliedParty.Num(); i++)
  582.     {
  583.         if (AlliedParty[i] && AlliedParty[i]->ActorHasTag(FName("Defender")) && !AlliedParty[i]->ActorHasTag(FName("Dead")))
  584.         {
  585.             return AlliedParty[i];
  586.         }
  587.     }
  588.     return nullptr;
  589. }
  590.  
  591. AEnemy* UFight::GetDefenderEnemy()
  592. {
  593.     if (EnemyParty.IsEmpty()) return nullptr;
  594.     for (int i = 0; i < EnemyParty.Num(); i++)
  595.     {
  596.         if (EnemyParty[i] && EnemyParty[i]->ActorHasTag(FName("Defender")))
  597.         {
  598.             return EnemyParty[i];
  599.         }
  600.     }
  601.     return nullptr;
  602. }
  603.  
  604. AAlly* UFight::GetSpecificTarget()
  605. {
  606.     for (int i = 1; i < AlliedParty.Num(); i++)
  607.     {
  608.         if (CurrentSkill && AlliedParty[i] && AlliedParty[i]->CharacterName == CurrentSkill->SpecificTargetName)
  609.         {
  610.             return AlliedParty[i];
  611.         }
  612.     }
  613.     return nullptr;
  614. }
  615.  
  616. USkill* UFight::GetEnemyHealingSkill(AEnemy* CurrentEnemy)
  617. {
  618.     if (CurrentEnemy->EquippedSkills.IsEmpty()) return nullptr;
  619.     for (USkill* Skill : CurrentEnemy->EquippedSkills)
  620.     {
  621.         if (Skill->SkillType == ESkillType::EST_Heal && Skill->ManaCost <= CurrentCharacter->Attributes->GetMana())
  622.         {
  623.             return Skill;
  624.         }
  625.     }
  626.     return nullptr;
  627. }
  628.  
  629. USkill* UFight::GetEnemySupportSkill(AEnemy* CurrentEnemy)
  630. {
  631.     if (CurrentEnemy->EquippedSkills.IsEmpty()) return nullptr;
  632.     for (USkill* Skill : CurrentEnemy->EquippedSkills)
  633.     {
  634.         if ((Skill->SkillType == ESkillType::EST_Support || Skill->SkillType == ESkillType::EST_AttackAlly)
  635.             && Skill->ManaCost <= CurrentCharacter->Attributes->GetMana())
  636.         {
  637.             return Skill;
  638.         }
  639.     }
  640.     return nullptr;
  641. }
  642.  
  643. USkill* UFight::GetEnemySummonSkill(AEnemy* CurrentEnemy)
  644. {
  645.     if (CurrentEnemy->EquippedSkills.IsEmpty()) return nullptr;
  646.  
  647.     for (USkill* Skill : CurrentEnemy->EquippedSkills)
  648.     {
  649.         if ((Skill->SkillType == ESkillType::EST_Summon)
  650.             && Skill->ManaCost <= CurrentCharacter->Attributes->GetMana())
  651.         {
  652.             return Skill;
  653.         }
  654.     }
  655.     return nullptr;
  656. }
  657.  
  658. TArray<USkill*> UFight::GetEnemyAttacks(AEnemy* CurrentEnemy)
  659. {
  660.     TArray<USkill*> EnemyAttacks;
  661.  
  662.     if (CurrentEnemy->EquippedSkills.IsEmpty()) return EnemyAttacks;
  663.  
  664.     for (USkill* Skill : CurrentEnemy->EquippedSkills)
  665.     {
  666.         if (Skill->SkillType == ESkillType::EST_Attack && Skill->SelfDamage<CurrentEnemy->Attributes->GetHealth()
  667.             && Skill->ManaCost <= CurrentCharacter->Attributes->GetMana())
  668.         {
  669.             EnemyAttacks.AddUnique(Skill);
  670.         }
  671.     }
  672.     return EnemyAttacks;
  673. }
  674.  
  675. TArray<ACombatCharacter*> UFight::BuildTargetArray()
  676. {
  677.     TArray<ACombatCharacter*> NewTargets;
  678.     if (CurrentCharacter == nullptr || CurrentSkill == nullptr || CurrentTarget == nullptr) return NewTargets;
  679.     if (CurrentSkill->NumberOfTargets == 0)
  680.     {
  681.         NewTargets = { CurrentCharacter };
  682.         return NewTargets;
  683.     }
  684.     if(CurrentTarget->IsA(AAlly::StaticClass()))
  685.     {
  686.         AAlly* AllyTarget = Cast<AAlly>(CurrentTarget);
  687.         int32 Index = AlliedParty.Find(AllyTarget);
  688.         for (int32 i = Index; i < Index + CurrentSkill->NumberOfTargets; i++)
  689.         {
  690.             if (i < AlliedParty.Num() && AlliedParty[i] && !AlliedParty[i]->ActorHasTag(FName("Dead")))
  691.             {
  692.                 NewTargets.Add(AlliedParty[i]);
  693.             }
  694.         }
  695.     }
  696.     if (CurrentTarget->IsA(AEnemy::StaticClass()))
  697.     {
  698.         AEnemy* EnemyTarget = Cast<AEnemy>(CurrentTarget);
  699.         int32 Index = EnemyParty.Find(EnemyTarget);
  700.         for (int32 i = Index; i < Index + CurrentSkill->NumberOfTargets; i++)
  701.         {
  702.             if (i < EnemyParty.Num())
  703.             {
  704.                 NewTargets.Add(EnemyParty[i]);
  705.             }
  706.         }
  707.     }
  708.     return NewTargets;
  709. }
  710.  
  711. TArray<int32> UFight::GetAvailableAllyRanks()
  712. {
  713.     TArray<int32> AliveAllyRanks;
  714.     for (AAlly* Ally : AlliedParty)
  715.     {
  716.         int32 AllyIndex = AlliedParty.Find(Ally);
  717.         if (CurrentSkill && CurrentSkill->ValidFirstTargetRanks.Contains(AllyIndex + 1)
  718.             && !Ally->ActorHasTag(FName("Dead")))
  719.         {
  720.             AliveAllyRanks.AddUnique(AllyIndex);
  721.         }
  722.     }
  723.     return AliveAllyRanks;
  724. }
  725.  
  726. void UFight::HandleOnSkillIconClicked(USkill* ClickedSkill)
  727. {
  728.     EnableMouseEvents();
  729.     if (ClickedSkill)
  730.     {
  731.         CurrentSkill = ClickedSkill;
  732.         MarkTargetsForSelection();
  733.         if (CurrentSkill->ManaCost > CurrentCharacter->Attributes->GetMana())
  734.         {
  735.             CurrentCharacter->ShowSpecialInfoText(TEXT("Za ma\u0142o many!"));
  736.             DisableMouseEvents();
  737.             return;
  738.         }
  739.         if (ClickedSkill->NumberOfTargets == 0)
  740.         {
  741.             Targets = { CurrentCharacter };
  742.             UseSkill();
  743.             DisableMouseEvents();
  744.             CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  745.             EndTurn();
  746.             return;
  747.         }
  748.     }
  749. }
  750.  
  751. void UFight::HandleOnEndTurnButtonClicked()
  752. {
  753.     if (CurrentCharacter && !CurrentCharacter->IsA(AEnemy::StaticClass()))
  754.     {
  755.         EndTurn();
  756.     }
  757. }
  758.  
  759. void UFight::HandleOnCharacterHover(ACombatCharacter* HoveredCharacter)
  760. {
  761.     if (HoveredCharacter == nullptr || CurrentSkill->NumberOfTargets <= 1) return;
  762.     if (HoveredCharacter->IsA(AAlly::StaticClass()))
  763.     {
  764.         int32 Index = AlliedParty.Find(Cast<AAlly>(HoveredCharacter));
  765.         for (int i = Index + 1; i < Index + CurrentSkill->NumberOfTargets; i++)
  766.         {
  767.             if (i >= AlliedParty.Num()) return;
  768.             AlliedParty[i]->SetArrowToColor();
  769.             AlliedParty[i]->ShowArrow();
  770.         }
  771.     }
  772.     else
  773.     {
  774.         AEnemy* CurrentEnemy = Cast<AEnemy>(HoveredCharacter);
  775.         if (!CurrentEnemy->IsValidLowLevel()) return;
  776.         //AEnemy* EnemyDefender = GetDefenderEnemy();
  777.         //if (EnemyDefender && EnemyDefender != CurrentEnemy)
  778.         //  return;
  779.         CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  780.         if(CurrentHUD && CurrentHUD->CombatOverlay)
  781.         {
  782.             CurrentHUD->CombatOverlay->SetNewEnemy(CurrentEnemy);
  783.         }
  784.         int32 Index = EnemyParty.Find(CurrentEnemy);
  785.         for (int i = Index + 1; i < Index + CurrentSkill->NumberOfTargets; i++)
  786.         {
  787.             if (i >= EnemyParty.Num()) return;
  788.             EnemyParty[i]->SetArrowToColor();
  789.             EnemyParty[i]->ShowArrow();
  790.         }
  791.     }
  792. }
  793.  
  794. void UFight::HandleOnCharacterEndHover(ACombatCharacter* HoveredCharacter)
  795. {
  796.     if (HoveredCharacter == nullptr || CurrentSkill->NumberOfTargets <= 1) return;
  797.     if (CurrentSkill->NumberOfTargets <= 1) return;
  798.     if (HoveredCharacter->IsA(AAlly::StaticClass()))
  799.     {
  800.         int32 Index = AlliedParty.Find(Cast<AAlly>(HoveredCharacter));
  801.         for (int i = Index + 1; i < Index + CurrentSkill->NumberOfTargets; i++)
  802.         {
  803.             if (i >= AlliedParty.Num()) return;
  804.             AlliedParty[i]->HideArrow();
  805.         }
  806.     }
  807.     else
  808.     {
  809.         int32 Index = EnemyParty.Find(Cast<AEnemy>(HoveredCharacter));
  810.         for (int i = Index + 1; i < Index + CurrentSkill->NumberOfTargets; i++)
  811.         {
  812.             if (i >= EnemyParty.Num()) return;
  813.             EnemyParty[i]->HideArrow();
  814.         }
  815.     }
  816. }
  817.  
  818. void UFight::HandleOnCharacterClicked(ACombatCharacter* ClickedCharacter)
  819. {
  820.     Targets.Empty();
  821.     ClearEnemyArrows();
  822.     if (ClickedCharacter == nullptr) return;
  823.     if (ClickedCharacter->IsA(AAlly::StaticClass()))
  824.     {
  825.         int32 Index = AlliedParty.Find(Cast<AAlly>(ClickedCharacter));
  826.         for (int i = Index; i < Index + CurrentSkill->NumberOfTargets; i++)
  827.         {
  828.             if (i >= AlliedParty.Num()) break;
  829.             Targets.Add(AlliedParty[i]);
  830.         }
  831.     }
  832.     else
  833.     {
  834.         AEnemy* CurrentEnemy = Cast<AEnemy>(ClickedCharacter);
  835.         AEnemy* EnemyDefender = GetDefenderEnemy();
  836.         if (CurrentEnemy && EnemyDefender && EnemyDefender != CurrentEnemy)
  837.             return;
  838.         int32 Index = EnemyParty.Find(CurrentEnemy);
  839.         for (int i = Index; i < Index + CurrentSkill->NumberOfTargets; i++)
  840.         {
  841.             if (i >= EnemyParty.Num()) break;
  842.             Targets.Add(EnemyParty[i]);
  843.         }
  844.     }
  845.     if (CurrentSkill && !Targets.IsEmpty())
  846.     {
  847.         if (CurrentSkill->bMelee)
  848.         {
  849.             TriggerMelee(CurrentCharacter);
  850.             DisableMouseEvents();
  851.         }
  852.         else
  853.         {
  854.             CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  855.             UseSkill();
  856.             EndTurn();
  857.         }
  858.     }
  859. }
  860.  
  861. void UFight::HandleOnTargetReached(ACombatCharacter* Character)
  862. {
  863.     if (Character && Character == CurrentCharacter)
  864.     {
  865.         UseSkillMelee();
  866.     }
  867. }
  868.  
  869. void UFight::HandleOnLocationReached(ACombatCharacter* Character)
  870. {
  871.     if (Character == nullptr || Character != CurrentCharacter) return;
  872.     Character->Flip(false);
  873.     if (Character->IsA(AAlly::StaticClass()))
  874.     {
  875.         Character->SetActorRotation(FRotator::ZeroRotator);
  876.     }
  877.     else
  878.     {
  879.         Character->SetActorRotation(FRotator(0.f, 180.f, 0.f));
  880.     }
  881.     Character->SetActorLocation(Character->TargetLocation);
  882.  
  883.     CurrentCharacter->GetWorldTimerManager().ClearTimer(TurnTimer);
  884.     EndTurn();
  885. }
  886.  
  887. void UFight::HandleOnCharacterDeath(ACombatCharacter* DeadCharacter)
  888. {
  889.     if (DeadCharacter->IsA(AAlly::StaticClass()))
  890.     {
  891.         AlliesAlive--;
  892.         if (AlliesAlive == 0)
  893.         {
  894.             Encounter->GetWorldTimerManager().SetTimer(TurnTimer, Encounter, &AFightEncounter::EndFightFailure, 2.f);
  895.         }
  896.     }
  897.     if (DeadCharacter->IsA(AEnemy::StaticClass()))
  898.     {
  899.         EnemiesAlive--;
  900.         Encounter->GainedExp += DeadCharacter->GetExperience();
  901.         if (EnemiesAlive == 0)
  902.         {
  903.             Encounter->GetWorldTimerManager().SetTimer(TurnTimer, Encounter, &AFightEncounter::EndFightSuccess, 1.5f);
  904.         }
  905.         EnemyParty.Remove(Cast<AEnemy>(DeadCharacter));
  906.         CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  907.         if (CurrentHUD && CurrentHUD->CombatOverlay)
  908.         {
  909.             CurrentHUD->CombatOverlay->SetNewEnemy(nullptr);
  910.         }
  911.         DeadCharacter->SetLifeSpan(2.f);
  912.     }
  913.     TurnQueue.Empty();
  914.     BuildTurnOrder();
  915. }
  916.  
  917. void UFight::UseSkill()
  918. {
  919.     if (CurrentCharacter == nullptr || CurrentSkill == nullptr || Targets.IsEmpty()) return;
  920.     CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  921.     if (CurrentHUD)
  922.     {
  923.         CurrentHUD->ShowInfoText(CurrentSkill->SkillName);
  924.     }
  925.     if (CurrentSkill->IsA(USummonSkill::StaticClass()))
  926.     {
  927.         USummonSkill* SummonSkill = Cast<USummonSkill>(CurrentSkill);
  928.         if (SummonSkill)
  929.         {
  930.             UseSummonSkill(SummonSkill);
  931.         }
  932.     }
  933.     CurrentSkill->UseSkill(CurrentCharacter, Targets);
  934. }
  935.  
  936. void UFight::UseSummonSkill(USummonSkill* Skill)
  937. {
  938.     int32 EnemyPartySize = EnemyParty.Num();
  939.     if (EnemyPartySize >= 4 || Encounter==nullptr)
  940.     {
  941.         return;
  942.     }
  943.     FVector DesiredLocation = EnemyParty[EnemyPartySize - 1]->GetActorLocation();
  944.     Encounter->OffestEnemySpawnLocation(DesiredLocation);
  945.     Encounter->SpawnEnemy(DesiredLocation, Skill->SummonedEnemyClasses);
  946. }
  947.  
  948. void UFight::UseItem(UItem* Item)
  949. {
  950.     CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  951.     if (CurrentHUD && CurrentHUD->InventoryWidget)
  952.     {
  953.         CurrentHUD->InventoryWidget->UpdateInventorySlots();
  954.         CurrentHUD->HideInventory();
  955.     }
  956.     AAlly* CurrentAlly = Cast<AAlly>(CurrentCharacter);
  957.     if (Item == nullptr || CurrentCharacter == nullptr || CurrentAlly == nullptr) return;
  958.     Item->UseItem(CurrentAlly);
  959.     CurrentAlly->bCanUseItems = false;
  960. }
  961.  
  962. void UFight::UseSkillMelee()
  963. {
  964.     UseSkill();
  965.     CurrentCharacter->GetWorldTimerManager().SetTimer(TurnTimer, this, &UFight::CharacterMoveToLocation, 1.f);
  966. }
  967.  
  968. void UFight::CharacterMoveToLocation()
  969. {
  970.     CurrentCharacter->bShouldMoveToLocation = true;
  971. }
  972.  
  973. void UFight::ClearEnemyArrows()
  974. {
  975.     for (AEnemy* Enemy : EnemyParty)
  976.     {
  977.         Enemy->HideArrow();
  978.     }
  979. }
  980.  
  981. void UFight::EnableMouseEvents()
  982. {
  983.     if (Controller)
  984.     {
  985.  
  986.         Controller->bEnableClickEvents = true;
  987.         Controller->bEnableMouseOverEvents = true;
  988.     }
  989. }
  990.  
  991. void UFight::DisableMouseEvents()
  992. {
  993.     if (Controller)
  994.     {
  995.         Controller->bEnableClickEvents = false;
  996.         Controller->bEnableMouseOverEvents = false;
  997.     }
  998. }
  999.  
  1000. inline bool UFight::IsFaster(ACombatCharacter* A, ACombatCharacter* B)
  1001. {
  1002.     return A->Attributes->Stats.Find(TEXT("Narwano\u015b\u0107")) >= B->Attributes->Stats.Find(TEXT("Narwano\u015b\u0107"));
  1003. }
  1004.  
  1005. //FightEncounter.h
  1006.  
  1007. #pragma once
  1008.  
  1009. #include "CoreMinimal.h"
  1010. #include "GameFramework/Actor.h"
  1011. #include "FightEncounter.generated.h"
  1012.  
  1013. DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnFightEndedDelegate);
  1014. class UFight;
  1015. class AEnemy;
  1016. class ADefaultGameMode;
  1017. class USpringArmComponent;
  1018. class UCameraComponent;
  1019. class USceneComponent;
  1020. class UAudioComponent;
  1021. class UItem;
  1022.  
  1023. UCLASS()
  1024. class WIRSPRAWIEDLIWOSCI_API AFightEncounter : public AActor
  1025. {
  1026.     GENERATED_BODY()
  1027.    
  1028. public:
  1029.     AFightEncounter();
  1030.  
  1031.     virtual void Tick(float DeltaTime) override;
  1032.  
  1033.     UFUNCTION(BlueprintCallable)
  1034.     void SpawnFirstEnemy();
  1035.  
  1036.     UFUNCTION(BlueprintCallable)
  1037.     virtual void StartFight();
  1038.  
  1039.     void EndFightSuccess();
  1040.     void EndFightFailure();
  1041.     void SpawnEnemyParty();
  1042.     void SpawnEnemy(FVector& Location, TArray<TSubclassOf<AEnemy>> EnemyClassArray);
  1043.     void SetupAllies();
  1044.     void OffsetAllyLocation(FVector& Location);
  1045.     void OffestEnemySpawnLocation(FVector& Location);
  1046.     void SetupAlliesAfterFightEnd();
  1047.     void PlayBattleSong();
  1048.     void StopBattleSong();
  1049.     void PlaySuccessSound();
  1050.     void PlayFailSound();
  1051.  
  1052.     void SwitchToCombatOverlay();
  1053.     void SwitchToPartyOverlay();
  1054.  
  1055.     UFUNCTION(BlueprintCallable)
  1056.     void EnableMouseCursor();
  1057.  
  1058.     UFUNCTION(BlueprintCallable)
  1059.     void DisableMouseCursor();
  1060.  
  1061.     ADefaultGameMode* CurrentGameMode;
  1062.  
  1063.     UPROPERTY(EditAnywhere)
  1064.     int16 Level;
  1065.  
  1066.     UPROPERTY(EditAnywhere)
  1067.     bool bIndoors;
  1068.  
  1069.     UPROPERTY(EditAnywhere)
  1070.     int32 RespawnsLeft;
  1071.  
  1072.     AEnemy* SpawnedEnemy;
  1073.  
  1074.     UPROPERTY(EditAnywhere)
  1075.     TSubclassOf<AEnemy> SpawnedEnemyClass;
  1076.  
  1077.     UPROPERTY(EditAnywhere)
  1078.     TArray<TSubclassOf<AEnemy>> EnemyPartyClassesRankOne;
  1079.  
  1080.     UPROPERTY(EditAnywhere)
  1081.     TArray<TSubclassOf<AEnemy>> EnemyPartyClassesRankTwo;
  1082.  
  1083.     UPROPERTY(EditAnywhere)
  1084.     TArray<TSubclassOf<AEnemy>> EnemyPartyClassesRankThree;
  1085.  
  1086.     UPROPERTY(EditAnywhere)
  1087.     TArray<TSubclassOf<AEnemy>> EnemyPartyClassesRankFour;
  1088.  
  1089.     UPROPERTY(EditAnywhere)
  1090.     TArray<TSubclassOf<UItem>> ItemRewardClasses;
  1091.  
  1092.     UPROPERTY()
  1093.     UItem* ItemReward;
  1094.  
  1095.     UPROPERTY()
  1096.     UFight* Fight;
  1097.  
  1098.     int32 GainedExp = 0;
  1099.  
  1100.     UPROPERTY(EditAnywhere)
  1101.     float MoneyReward = 0.f;
  1102.  
  1103.     UPROPERTY(EditAnywhere, Category = Sound)
  1104.     TArray<USoundBase*> BattleSongs;
  1105.  
  1106.     UPROPERTY(EditAnywhere, Category = Sound)
  1107.     USoundBase* SuccessSound;
  1108.  
  1109.     UPROPERTY(EditAnywhere, Category = Sound)
  1110.     USoundBase* FailSound;
  1111.  
  1112.     UPROPERTY(BlueprintAssignable, Category = Events)
  1113.     FOnFightEndedDelegate OnFightEnded;
  1114. protected:
  1115.     virtual void BeginPlay() override;
  1116.  
  1117.     UPROPERTY(EditAnywhere)
  1118.     bool bUseYAxis = false;
  1119.  
  1120.     UPROPERTY(EditAnywhere)
  1121.     USceneComponent* MainComponent;
  1122.  
  1123.     UPROPERTY(EditAnywhere)
  1124.     UCameraComponent* Camera;
  1125.  
  1126.     UPROPERTY(EditAnywhere)
  1127.     UAudioComponent* MusicPlayer;
  1128.  
  1129.     FTimerHandle FightEndTimer;
  1130. };
  1131.  
  1132. //FightEncounter.cpp
  1133. #include "GameMechanics/Combat/FightEncounter.h"
  1134. #include "GameMechanics/Combat/Fight.h"
  1135. #include "GameMechanics/GameModes/DefaultGameMode.h"
  1136. #include "GameMechanics/AttributeComponent.h"
  1137. #include "GameMechanics/Skill.h"
  1138. #include "Characters/Enemy.h"
  1139. #include "Characters/Ally.h"
  1140. #include "Characters/MainCharacter.h"
  1141. #include "AIController.h"
  1142. #include "Kismet/GameplayStatics.h"
  1143. #include "Components/SceneComponent.h"
  1144. #include "Components/AudioComponent.h"
  1145. #include "GameFramework/SpringArmComponent.h"
  1146. #include "Camera/CameraComponent.h"
  1147. #include "UI/DefaultHUD.h"
  1148. #include "UI/CombatOverlay.h"
  1149. #include "Items/Item.h"
  1150.  
  1151. AFightEncounter::AFightEncounter()
  1152. {
  1153.     PrimaryActorTick.bCanEverTick = true;
  1154.     MainComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
  1155.     SetRootComponent(MainComponent);
  1156.     Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
  1157.     Camera->SetupAttachment(GetRootComponent());
  1158.     MusicPlayer = CreateDefaultSubobject<UAudioComponent>(TEXT("Music Player"));
  1159.     MusicPlayer->SetupAttachment(GetRootComponent());
  1160. }
  1161.  
  1162. void AFightEncounter::BeginPlay()
  1163. {
  1164.     Super::BeginPlay();
  1165.  
  1166.     MusicPlayer->Stop();
  1167.     if(Tags.IsEmpty())
  1168.     {
  1169.         SpawnFirstEnemy();
  1170.     }
  1171. }
  1172.  
  1173. void AFightEncounter::SpawnFirstEnemy() //spawns enemy who chases you
  1174. {
  1175.     if (GetWorld())
  1176.     {
  1177.         if(RespawnsLeft <= 0) return;
  1178.         SpawnedEnemy = GetWorld()->SpawnActor<AEnemy>(SpawnedEnemyClass, MainComponent->GetComponentLocation(), FRotator::ZeroRotator);
  1179.         if (SpawnedEnemy)
  1180.         {
  1181.             SpawnedEnemy->SpawnerEncounter = this;
  1182.             AAIController* NewAIController = GetWorld()->SpawnActor<AAIController>(AAIController::StaticClass(), GetActorLocation(), FRotator::ZeroRotator);
  1183.             NewAIController->Possess(SpawnedEnemy);
  1184.             SpawnedEnemy->AIController = NewAIController;
  1185.         }
  1186.     }
  1187.     CurrentGameMode = Cast<ADefaultGameMode>(UGameplayStatics::GetGameMode(this));
  1188. }
  1189.  
  1190. void AFightEncounter::Tick(float DeltaTime)
  1191. {
  1192.     Super::Tick(DeltaTime);
  1193. }
  1194.  
  1195. void AFightEncounter::StartFight()
  1196. {
  1197.     Fight = nullptr;
  1198.     if (RespawnsLeft <= 0) return;
  1199.     RespawnsLeft--;
  1200.     if(SpawnedEnemy)
  1201.     {
  1202.         SpawnedEnemy->Destroy();
  1203.     }
  1204.     Fight = NewObject<UFight>(this, UFight::StaticClass());
  1205.     Fight->Encounter = this;
  1206.     CurrentGameMode = Cast<ADefaultGameMode>(UGameplayStatics::GetGameMode(this));
  1207.     if (CurrentGameMode == nullptr) return;
  1208.     Fight->CurrentGameMode = CurrentGameMode;
  1209.     ADefaultHUD* CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  1210.     Fight->CurrentHUD = CurrentHUD;
  1211.     CurrentHUD->ShowInfoText(TEXT("WALKA!"));
  1212.     CurrentGameMode->CurrentMode = ECurrentMode::ECM_Combat;
  1213.  
  1214.     APlayerController* Controller = GetWorld()->GetFirstPlayerController();
  1215.     Fight->Controller = Controller;
  1216.     Fight->AddItemClickedEvents();
  1217.  
  1218.     Controller->SetViewTargetWithBlend(this, 1.f);
  1219.     SpawnEnemyParty();
  1220.  
  1221.     SetupAllies();
  1222.  
  1223.     SwitchToCombatOverlay();
  1224.     Fight->BuildTurnOrder();
  1225.     Fight->StartTurn();
  1226.     EnableMouseCursor();
  1227.     PlayBattleSong();
  1228. }
  1229.  
  1230. void AFightEncounter::EndFightSuccess()
  1231. {
  1232.     StopBattleSong();
  1233.     PlaySuccessSound();
  1234.     CurrentGameMode = Cast<ADefaultGameMode>(UGameplayStatics::GetGameMode(this));
  1235.     if (CurrentGameMode)
  1236.     {
  1237.         if (bIndoors)
  1238.         {
  1239.             CurrentGameMode->CurrentMode = ECurrentMode::ECM_ExplorationInterior;
  1240.         }
  1241.         else
  1242.         {
  1243.             CurrentGameMode->CurrentMode = ECurrentMode::ECM_Exploration;
  1244.         }
  1245.         SwitchToPartyOverlay();
  1246.         ADefaultHUD* CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  1247.         if(!ItemRewardClasses.IsEmpty())
  1248.         {
  1249.             int32 ItemIndex = FMath::RandRange(0, ItemRewardClasses.Num() - 1);
  1250.             ItemReward = NewObject<UItem>(GetOuter(), ItemRewardClasses[ItemIndex]);
  1251.             ItemReward->Quantity = 1;
  1252.             ItemReward->AddToInventory();
  1253.         }
  1254.         CurrentGameMode->Money += MoneyReward;
  1255.         if (CurrentHUD)
  1256.         {
  1257.             CurrentHUD->ShowVictoryDialogue(GainedExp, ItemReward, MoneyReward);
  1258.         }
  1259.         AMainCharacter* MainCharacter = Cast<AMainCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
  1260.         if (MainCharacter == nullptr) return;
  1261.         if(MainCharacter->Ult)
  1262.         {
  1263.             MainCharacter->Ult->bUsable = true;
  1264.         }
  1265.         APlayerController* Controller = GetWorld()->GetFirstPlayerController();
  1266.         Controller->SetViewTargetWithBlend(MainCharacter, 1.f);
  1267.         GetWorldTimerManager().SetTimer(FightEndTimer, this, &AFightEncounter::SetupAlliesAfterFightEnd, 1.f);
  1268.         OnFightEnded.Broadcast();
  1269.     }
  1270. }
  1271.  
  1272. void AFightEncounter::EndFightFailure()
  1273. {
  1274.     StopBattleSong();
  1275.     ADefaultHUD* CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  1276.     if (CurrentHUD)
  1277.     {
  1278.         CurrentHUD->ShowGameOverDialogue();
  1279.     }
  1280.     UGameplayStatics::GetPlayerController(this, 0)->SetPause(true);
  1281.     PlayFailSound();
  1282. }
  1283.  
  1284. void AFightEncounter::SpawnEnemyParty()
  1285. {
  1286.     FVector Location = GetActorLocation();
  1287.  
  1288.     SpawnEnemy(Location, EnemyPartyClassesRankOne);
  1289.     OffestEnemySpawnLocation(Location);
  1290.     SpawnEnemy(Location, EnemyPartyClassesRankTwo);
  1291.     OffestEnemySpawnLocation(Location);
  1292.     SpawnEnemy(Location, EnemyPartyClassesRankThree);
  1293.     OffestEnemySpawnLocation(Location);
  1294.     SpawnEnemy(Location, EnemyPartyClassesRankFour);
  1295.     Fight->EnemiesAlive = Fight->EnemyParty.Num();
  1296. }
  1297.  
  1298. void AFightEncounter::SpawnEnemy(FVector& Location, TArray<TSubclassOf<AEnemy>> EnemyClassArray)
  1299. {
  1300.     int32 RandomIndex;
  1301.     if (!EnemyClassArray.IsEmpty())
  1302.     {
  1303.         RandomIndex = FMath::RandRange(0, EnemyClassArray.Num()-1);
  1304.         FRotator Rotator;
  1305.         if (!bUseYAxis)
  1306.         {
  1307.             Rotator = FRotator(0.f, 180.f, 0.f);
  1308.         }
  1309.         else
  1310.         {
  1311.             Rotator = FRotator(0.f, -90.f, 0.f);
  1312.         }
  1313.         AEnemy* NewEnemy = GetWorld()->SpawnActor<AEnemy>(EnemyClassArray[RandomIndex],
  1314.             Location, Rotator);
  1315.  
  1316.         //used for melee skills to return to the initial location
  1317.         NewEnemy->InitialLocation = Location;
  1318.         if(NewEnemy && CurrentGameMode)
  1319.         {
  1320.             NewEnemy->Attributes->SetLevel(Level);
  1321.             CurrentGameMode->InitializeCharacter(NewEnemy, CurrentGameMode->FindEnemy(NewEnemy));
  1322.             CurrentGameMode->InitializeEnemySkills(NewEnemy, Level);
  1323.             FActorSpawnParameters ControllerSpawnParams;
  1324.             ControllerSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
  1325.             AAIController* NewAIController = GetWorld()->SpawnActor<AAIController>(AAIController::StaticClass(), NewEnemy->GetActorLocation(), FRotator::ZeroRotator, ControllerSpawnParams);
  1326.             NewAIController->Possess(NewEnemy);
  1327.             NewEnemy->AIController = NewAIController;
  1328.             NewEnemy->DisableSphereCollisions();
  1329.             NewEnemy->ShowWidget();
  1330.             NewEnemy->ChangeFlipbook(TEXT("IdleCombat"));
  1331.             Fight->EnemyParty.Add(NewEnemy);
  1332.             NewEnemy->Rank = Fight->EnemyParty.Find(NewEnemy) + 1;
  1333.             NewEnemy->OnCharacterHover.AddDynamic(Fight, &UFight::HandleOnCharacterHover);
  1334.             NewEnemy->OnCharacterEndHover.AddDynamic(Fight, &UFight::HandleOnCharacterEndHover);
  1335.             NewEnemy->OnCharacterClicked.AddDynamic(Fight, &UFight::HandleOnCharacterClicked);
  1336.             NewEnemy->OnTargetReached.AddDynamic(Fight, &UFight::HandleOnTargetReached);
  1337.             NewEnemy->OnLocationReached.AddDynamic(Fight, &UFight::HandleOnLocationReached);
  1338.             NewEnemy->OnCharacterDeath.AddDynamic(Fight, &UFight::HandleOnCharacterDeath);
  1339.         }
  1340.     }
  1341. }
  1342.  
  1343. void AFightEncounter::SetupAllies()
  1344. {
  1345.     Fight->AlliedParty.Empty();
  1346.     if (CurrentGameMode == nullptr) return;
  1347.     Fight->AlliedParty = CurrentGameMode->AlliedParty;
  1348.     Fight->AlliesAlive = Fight->AlliedParty.Num();
  1349.     AMainCharacter* MainCharacter = Cast<AMainCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
  1350.     if (MainCharacter)
  1351.     {
  1352.         MainCharacter->SetControllerRotation(GetActorRotation());
  1353.         MainCharacter->SetActorRotation(FRotator::ZeroRotator);
  1354.         MainCharacter->Flip(false);
  1355.         if (MainCharacter->Ult && (MainCharacter->Attributes == nullptr || MainCharacter->Attributes->GetRage() < MainCharacter->Attributes->GetMaxRage()))
  1356.         {
  1357.             MainCharacter->Ult->bUsable = false;
  1358.         }
  1359.         else if(MainCharacter->Ult)
  1360.         {
  1361.             MainCharacter->Ult->bUsable = true;
  1362.         }
  1363.     }
  1364.     FVector Location;
  1365.     if(!bUseYAxis)
  1366.     {
  1367.         Location = GetActorLocation() - FVector(200.f, 0.f, 0.f);
  1368.     }
  1369.     else
  1370.     {
  1371.         Location = GetActorLocation() - FVector(0.f, 200.f, 0.f);
  1372.     }
  1373.     for (AAlly* Ally : CurrentGameMode->AlliedParty)
  1374.     {
  1375.         Ally->SetActorLocation(Location);
  1376.         Ally->InitialLocation = Location;
  1377.        
  1378.         Ally->Flip(false);
  1379.         Ally->ShowWidget();
  1380.         Ally->HideArrow();
  1381.         Ally->UpdateEffectIcons();
  1382.         Ally->ChangeFlipbook(TEXT("IdleCombat"));
  1383.         Ally->OnCharacterHover.AddDynamic(Fight, &UFight::HandleOnCharacterHover);
  1384.         Ally->OnCharacterEndHover.AddDynamic(Fight, &UFight::HandleOnCharacterEndHover);
  1385.         Ally->OnCharacterClicked.AddDynamic(Fight, &UFight::HandleOnCharacterClicked);
  1386.         Ally->OnTargetReached.AddDynamic(Fight, &UFight::HandleOnTargetReached);
  1387.         Ally->OnLocationReached.AddDynamic(Fight, &UFight::HandleOnLocationReached);
  1388.         Ally->OnCharacterDeath.AddDynamic(Fight, &UFight::HandleOnCharacterDeath);
  1389.         OffsetAllyLocation(Location);
  1390.     }
  1391. }
  1392.  
  1393. void AFightEncounter::OffsetAllyLocation(FVector& Location)
  1394. {
  1395.     if (bUseYAxis)
  1396.     {
  1397.         Location.Y -= 100.f;
  1398.         return;
  1399.     }
  1400.     Location.X -= 100.f;
  1401. }
  1402.  
  1403. void AFightEncounter::OffestEnemySpawnLocation(FVector& Location)
  1404. {
  1405.     if (bUseYAxis)
  1406.     {
  1407.         Location.Y += 100.f;
  1408.         return;
  1409.     }
  1410.     Location.X += 100.f;
  1411. }
  1412.  
  1413. void AFightEncounter::SetupAlliesAfterFightEnd()
  1414. {
  1415.     if (CurrentGameMode == nullptr) return;
  1416.     for (AAlly* Ally : CurrentGameMode->AlliedParty)
  1417.     {
  1418.         Ally->Turn = 0;
  1419.         Ally->HideWidget();
  1420.         Ally->ChangeFlipbook(TEXT("Idle"));
  1421.         if (Ally->ActorHasTag(FName("Dead")))
  1422.         {
  1423.             Ally->bIsAlive = true;
  1424.             Ally->Tags.Remove(FName("Dead"));
  1425.             Ally->Attributes->SetHealth(Ally->Attributes->GetMaxHealth() / 2.f);
  1426.         }
  1427.         int32 AllyExp = Ally->GetExperience();
  1428.         Ally->SetExperience(AllyExp + GainedExp);
  1429.     }
  1430.     for (AAlly* Ally : CurrentGameMode->AvailableAllies)
  1431.     {
  1432.         if (!CurrentGameMode->AlliedParty.Contains(Ally))
  1433.         {
  1434.             int32 AllyExp = Ally->GetExperience();
  1435.             Ally->SetExperience(AllyExp + (GainedExp/2));
  1436.         }
  1437.     }
  1438. }
  1439.  
  1440. void AFightEncounter::PlayBattleSong()
  1441. {
  1442.     if (BattleSongs.IsEmpty()) return;
  1443.     USoundBase* BattleSong = BattleSongs[FMath::RandRange(0, BattleSongs.Num() - 1)];
  1444.     if(BattleSong)
  1445.     {
  1446.         MusicPlayer->SetSound(BattleSong);
  1447.         MusicPlayer->Play();
  1448.     }
  1449. }
  1450.  
  1451. void AFightEncounter::StopBattleSong()
  1452. {
  1453.     if (MusicPlayer->IsPlaying())
  1454.     {
  1455.         MusicPlayer->Stop();
  1456.     }
  1457. }
  1458.  
  1459. void AFightEncounter::PlaySuccessSound()
  1460. {
  1461.     if (SuccessSound)
  1462.     {
  1463.         UGameplayStatics::PlaySound2D(this, SuccessSound);
  1464.     }
  1465. }
  1466.  
  1467. void AFightEncounter::PlayFailSound()
  1468. {
  1469.     if (FailSound)
  1470.     {
  1471.         UGameplayStatics::PlaySound2D(this, FailSound);
  1472.     }
  1473. }
  1474.  
  1475. void AFightEncounter::SwitchToCombatOverlay()
  1476. {
  1477.     ADefaultHUD* CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  1478.     if (CurrentHUD)
  1479.     {
  1480.         CurrentHUD->SwitchToCombatOverlay();
  1481.     }
  1482.     if (Fight && CurrentHUD && CurrentHUD->CombatOverlay)
  1483.     {
  1484.         CurrentHUD->CombatOverlay->OnEndTurnButtonClicked.AddDynamic(Fight, &UFight::HandleOnEndTurnButtonClicked);
  1485.     }
  1486. }
  1487.  
  1488. void AFightEncounter::SwitchToPartyOverlay()
  1489. {
  1490.     ADefaultHUD* CurrentHUD = Cast<ADefaultHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
  1491.     if (CurrentHUD)
  1492.     {
  1493.         CurrentHUD->SwitchToPartyOverlay();
  1494.     }
  1495. }
  1496.  
  1497. void AFightEncounter::EnableMouseCursor()
  1498. {
  1499.     GetWorld()->GetFirstPlayerController()->bShowMouseCursor = true;
  1500. }
  1501.  
  1502. void AFightEncounter::DisableMouseCursor()
  1503. {
  1504.     GetWorld()->GetFirstPlayerController()->bShowMouseCursor = false;
  1505. }
Tags: C++ ue5
Advertisement
Add Comment
Please, Sign In to add comment