HAxis sos
This commit is contained in:
61
Source/UnrealProject/GUI/HUD/AbilityButton.cpp
Normal file
61
Source/UnrealProject/GUI/HUD/AbilityButton.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "AbilityButton.h"
|
||||
#include "NetworkCharacter.h"
|
||||
#include "AbilityInfo.h"
|
||||
#include "AbilityState.h"
|
||||
|
||||
void UAbilityButton::NativeConstruct()
|
||||
{
|
||||
m_globalEnable = true;
|
||||
Super::NativeConstruct();
|
||||
SetCooldown(1.0f);
|
||||
SetToggled(false);
|
||||
SetupButton(nullptr, false);
|
||||
}
|
||||
|
||||
UAbilityInfo* UAbilityButton::GetAbility()
|
||||
{
|
||||
return m_abilityInfo;
|
||||
}
|
||||
|
||||
void UAbilityButton::InitButton(class UAbilityInfo* info, int32 index, bool alt)
|
||||
{
|
||||
if (info)
|
||||
{
|
||||
SetCooldown(1.0f);
|
||||
SetToggled(false);
|
||||
SetupButton(info, false);
|
||||
SetIndex(index, alt);
|
||||
SetAbilityAvailable(true);
|
||||
m_index = index;
|
||||
m_abilityInfo = info;
|
||||
}
|
||||
}
|
||||
|
||||
bool UAbilityButton::IsAssigned() const
|
||||
{
|
||||
return m_abilityInfo != nullptr;
|
||||
}
|
||||
|
||||
void UAbilityButton::UpdateState(class AAbilityState* state, ANetworkCharacter* character)
|
||||
{
|
||||
SetToggled(state->toggleState);
|
||||
SetCooldown(state->cooldownRate);
|
||||
SetAbilityAvailable(character->GetMana() >= state->info->mana);
|
||||
}
|
||||
|
||||
void UAbilityButton::SetButtonEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
if (m_abilityInfo)
|
||||
{
|
||||
SetupButton(m_abilityInfo, m_enabled && m_globalEnable);
|
||||
}
|
||||
}
|
||||
void UAbilityButton::SetGlobalEnable(bool enabled)
|
||||
{
|
||||
m_globalEnable = enabled;
|
||||
SetupButton(m_abilityInfo, m_enabled && m_globalEnable);
|
||||
}
|
||||
42
Source/UnrealProject/GUI/HUD/AbilityButton.h
Normal file
42
Source/UnrealProject/GUI/HUD/AbilityButton.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "AbilityButton.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UAbilityButton : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void NativeConstruct() override;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Button")
|
||||
void SetupButton(class UAbilityInfo* info, bool enabled);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Button")
|
||||
void SetCooldown(float cooldown);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Button")
|
||||
void SetToggled(bool toggled);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Button")
|
||||
void SetIndex(int32 index, bool alt);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Button")
|
||||
void SetAbilityAvailable(bool available);
|
||||
|
||||
class UAbilityInfo* GetAbility();
|
||||
|
||||
void InitButton(class UAbilityInfo* info, int32 index, bool alt);
|
||||
bool IsAssigned() const;
|
||||
void UpdateState(class AAbilityState* state, class ANetworkCharacter* character);
|
||||
void SetButtonEnabled(bool enabled);
|
||||
void SetGlobalEnable(bool enabled);
|
||||
private:
|
||||
int32 m_index;
|
||||
bool m_enabled;
|
||||
bool m_globalEnable;
|
||||
class UAbilityInfo* m_abilityInfo;
|
||||
};
|
||||
160
Source/UnrealProject/GUI/HUD/ButtonBarSwitcher.cpp
Normal file
160
Source/UnrealProject/GUI/HUD/ButtonBarSwitcher.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "AbilityButton.h"
|
||||
#include "ButtonBarSwitcher.h"
|
||||
#include "BaseSkillObject.h"
|
||||
#include "AbilityState.h"
|
||||
#include "NetworkPlayer.h"
|
||||
#include "IngameSkillTree.h"
|
||||
#include "AbilityInfo.h"
|
||||
|
||||
void UButtonBarSwitcher::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
m_globalEnable = true;
|
||||
m_alternateSkillSet = false;
|
||||
m_FindAndAddButtonBar("ButtonBarMain");
|
||||
m_FindAndAddButtonBar("ButtonBarAlt");
|
||||
}
|
||||
|
||||
bool UButtonBarSwitcher::AssignSkillButton(const FIngameSkillTreeSkill& skill, bool isAlt)
|
||||
{
|
||||
if (m_mappedButtons.Find(skill.selectedEffect))
|
||||
return true;
|
||||
|
||||
int32 bar = isAlt ? 1 : 0;
|
||||
if (bar >= m_buttonBars.Num())
|
||||
return false;
|
||||
|
||||
UAbilityButton* targetButton;
|
||||
if(!m_buttonBars[bar]->AssignSkillButton(skill, targetButton, isAlt))
|
||||
{
|
||||
GERROR("Too many skills, can't assign " + skill.selectedEffect->GetName() + " to bar " + bar);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mappedButtons.Add(skill.selectedEffect, targetButton);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UButtonBarSwitcher::UpdateCooldowns(TArray<class AAbilityState*> abilityStates, ANetworkPlayer* player)
|
||||
{
|
||||
for (int32 i = 0; i < abilityStates.Num(); i++)
|
||||
{
|
||||
UAbilityButton** button = m_mappedButtons.Find(abilityStates[i]->info);
|
||||
if (button)
|
||||
{
|
||||
(*button)->UpdateState(abilityStates[i], player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UButtonBar* UButtonBarSwitcher::m_FindAndAddButtonBar(const FName& name)
|
||||
{
|
||||
UButtonBar* bar = Cast<UButtonBar>(WidgetTree->FindWidget(name));
|
||||
if (bar)
|
||||
{
|
||||
m_buttonBars.Add(bar);
|
||||
}
|
||||
return bar;
|
||||
}
|
||||
|
||||
void UButtonBarSwitcher::SetSkillButtonEnabled(const FIngameSkillTreeSkill& skill, bool enabled)
|
||||
{
|
||||
UAbilityButton** button = m_mappedButtons.Find(skill.selectedEffect);
|
||||
if (button)
|
||||
{
|
||||
(*button)->SetButtonEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void UButtonBarSwitcher::SetGlobalEnable(bool enabled)
|
||||
{
|
||||
for(UButtonBar* bb : m_buttonBars)
|
||||
{
|
||||
bb->SetGlobalEnable(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
class UAbilityInfo* UButtonBarSwitcher::GetAbilityMapping(int32 index)
|
||||
{
|
||||
if(m_buttonBars.Num() != 2)
|
||||
{
|
||||
GERROR("m_buttonBars.Num() != 2");
|
||||
return nullptr;
|
||||
}
|
||||
UButtonBar* currentBar = m_buttonBars[m_alternateSkillSet ? 1 : 0];
|
||||
if(index < 0 || index >= currentBar->buttons.Num())
|
||||
return nullptr;
|
||||
return currentBar->buttons[index]->GetAbility();
|
||||
}
|
||||
class UAbilityInfo* UButtonBarSwitcher::GetAbilityMapping(int32 index, bool isAlt)
|
||||
{
|
||||
if(m_buttonBars.Num() != 2)
|
||||
{
|
||||
GERROR("m_buttonBars.Num() != 2");
|
||||
return nullptr;
|
||||
}
|
||||
UButtonBar* currentBar = m_buttonBars[isAlt ? 1 : 0];
|
||||
if(index < 0 || index >= currentBar->buttons.Num())
|
||||
return nullptr;
|
||||
return currentBar->buttons[index]->GetAbility();
|
||||
}
|
||||
|
||||
void UButtonBarSwitcher::TransitionToAlternateSkillSet_Implementation()
|
||||
{
|
||||
}
|
||||
void UButtonBarSwitcher::TransitionToMainSkillSet_Implementation()
|
||||
{
|
||||
}
|
||||
void UButtonBarSwitcher::ToggleSkillSet(bool useAlternateSkillSet)
|
||||
{
|
||||
if (m_alternateSkillSet != useAlternateSkillSet)
|
||||
{
|
||||
if(useAlternateSkillSet)
|
||||
TransitionToAlternateSkillSet();
|
||||
else
|
||||
TransitionToMainSkillSet();
|
||||
m_alternateSkillSet = useAlternateSkillSet;
|
||||
}
|
||||
}
|
||||
|
||||
void UButtonBar::NativeConstruct()
|
||||
{
|
||||
TArray<UWidget*> widgets;
|
||||
WidgetTree->GetAllWidgets(widgets);
|
||||
for (int32 i = 0; i < widgets.Num(); i++)
|
||||
{
|
||||
UAbilityButton* button = Cast<UAbilityButton>(widgets[i]);
|
||||
if (button)
|
||||
{
|
||||
buttons.Add(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UButtonBar::AssignSkillButton(const FIngameSkillTreeSkill& skill, class UAbilityButton*& buttonOut, bool alt)
|
||||
{
|
||||
for (int32 i = 0; i < buttons.Num(); i++)
|
||||
{
|
||||
if (buttons[i]->IsAssigned())
|
||||
continue;
|
||||
buttonOut = buttons[i];
|
||||
buttonOut->InitButton(skill.selectedEffect, i, alt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UButtonBar::SetGlobalEnable(bool enabled)
|
||||
{
|
||||
for(UAbilityButton* button : buttons)
|
||||
{
|
||||
if(button)
|
||||
{
|
||||
button->SetGlobalEnable(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Source/UnrealProject/GUI/HUD/ButtonBarSwitcher.h
Normal file
58
Source/UnrealProject/GUI/HUD/ButtonBarSwitcher.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "ButtonBarSwitcher.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UButtonBar : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
bool AssignSkillButton(const struct FIngameSkillTreeSkill& skill, class UAbilityButton*& buttonOut, bool alt);
|
||||
|
||||
void SetGlobalEnable(bool enabled);
|
||||
|
||||
UPROPERTY()
|
||||
TArray<class UAbilityButton*> buttons;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UButtonBarSwitcher : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
bool AssignSkillButton(const struct FIngameSkillTreeSkill& skill, bool isAlt);
|
||||
void UpdateCooldowns(TArray<class AAbilityState*> abilityStates, class ANetworkPlayer* player);
|
||||
|
||||
void SetSkillButtonEnabled(const struct FIngameSkillTreeSkill& skill, bool enabled);
|
||||
|
||||
// Set the global enabled button state
|
||||
void SetGlobalEnable(bool enabled);
|
||||
|
||||
class UAbilityInfo* GetAbilityMapping(int32 index);
|
||||
class UAbilityInfo* GetAbilityMapping(int32 index, bool isAlt);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category="Animation")
|
||||
void TransitionToAlternateSkillSet();
|
||||
UFUNCTION(BlueprintNativeEvent, Category="Animation")
|
||||
void TransitionToMainSkillSet();
|
||||
|
||||
void ToggleSkillSet(bool useAlternateSkillSet);
|
||||
|
||||
private:
|
||||
UButtonBar* m_FindAndAddButtonBar(const FName& name);
|
||||
|
||||
bool m_globalEnable;
|
||||
bool m_alternateSkillSet;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<UButtonBar*> m_buttonBars;
|
||||
UPROPERTY()
|
||||
TMap<class UAbilityInfo*, UAbilityButton*> m_mappedButtons;
|
||||
};
|
||||
126
Source/UnrealProject/GUI/HUD/HealthBar.cpp
Normal file
126
Source/UnrealProject/GUI/HUD/HealthBar.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "HealthBar.h"
|
||||
#include "StatBar.h"
|
||||
|
||||
// 1 = Crown
|
||||
// 2 = Mini-Boss
|
||||
// 3 = Dot
|
||||
// 4 = Camp
|
||||
// 5 = PlayerIcon
|
||||
static UTexture2D* barIcons[6];
|
||||
UHealthBar::UHealthBar(const FObjectInitializer& init) : Super(init)
|
||||
{
|
||||
barIcons[0] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/Minimap/T_IconCrown").Object;
|
||||
barIcons[1] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/Minimap/T_IconMini").Object;
|
||||
barIcons[2] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/Minimap/T_IconDot").Object;
|
||||
barIcons[3] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/Minimap/T_IconCamp").Object;
|
||||
barIcons[4] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/Minimap/T_IconPlayer").Object;
|
||||
}
|
||||
|
||||
void UHealthBar::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
m_currentIcon = (EMinimapIcon)-1;
|
||||
m_HP = Cast<UStatBar>(WidgetTree->FindWidget("HP"));
|
||||
m_mana = Cast<UStatBar>(WidgetTree->FindWidget("Mana"));
|
||||
m_styleSwitcher = Cast<UWidgetSwitcher>(WidgetTree->FindWidget("StyleSwitcher"));
|
||||
m_HP1 = Cast<UStatBar>(WidgetTree->FindWidget("HP1"));
|
||||
m_icon = Cast<UImage>(WidgetTree->FindWidget("Icon"));
|
||||
m_name = Cast<UTextBlock>(WidgetTree->FindWidget("Name"));
|
||||
SetName("");
|
||||
SetIcon(EMinimapIcon::None);
|
||||
if(m_mana)
|
||||
{
|
||||
m_mana->SetBarColor(EBarColor::Blue);
|
||||
}
|
||||
m_style = 0;
|
||||
m_friendly = false;
|
||||
}
|
||||
|
||||
void UHealthBar::NativeDestruct()
|
||||
{
|
||||
Super::NativeDestruct();
|
||||
}
|
||||
|
||||
void UHealthBar::SetIcon(EMinimapIcon _iconID)
|
||||
{
|
||||
if(!m_icon)
|
||||
return;
|
||||
if(_iconID == m_currentIcon)
|
||||
return;
|
||||
int32 iconID = FMath::Clamp((int32)_iconID, 0, 5);
|
||||
if(iconID == 0)
|
||||
m_icon->SetVisibility(ESlateVisibility::Collapsed);
|
||||
else
|
||||
{
|
||||
m_icon->SetBrushFromTexture(barIcons[iconID - 1]);
|
||||
m_icon->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
}
|
||||
}
|
||||
|
||||
void UHealthBar::SetStyle(int32 style)
|
||||
{
|
||||
if(style == m_style)
|
||||
return;
|
||||
m_style = FMath::Clamp(style, 0, 1);
|
||||
m_styleSwitcher->SetActiveWidgetIndex(m_style);
|
||||
}
|
||||
void UHealthBar::UpdateHealth(int32 curr, int32 max)
|
||||
{
|
||||
m_updateCount++;
|
||||
bool showAnimation = m_updateCount > 8;
|
||||
if(m_style == 0)
|
||||
{
|
||||
m_HP->SetStat(curr, max, showAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HP1->SetStat(curr, max, showAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
void UHealthBar::UpdateMana(int32 curr, int32 max, float blocked)
|
||||
{
|
||||
if(m_style == 0)
|
||||
{
|
||||
m_mana->SetStat(curr, max, true);
|
||||
}
|
||||
}
|
||||
|
||||
void UHealthBar::UpdateAlignment(bool friendly)
|
||||
{
|
||||
m_friendly = friendly;
|
||||
|
||||
const FLinearColor colorFriendly = FLinearColor(0.18f, 0.8f, 0.23f);
|
||||
const FLinearColor colorEnemy = FLinearColor(0.73f, 0.1f, 0.13f);
|
||||
|
||||
if(m_style == 0)
|
||||
{
|
||||
m_HP->SetBarColor(friendly ? EBarColor::Green : EBarColor::Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HP1->SetBarColor(friendly ? EBarColor::Green : EBarColor::Red);
|
||||
}
|
||||
}
|
||||
|
||||
void UHealthBar::SetName(FString name)
|
||||
{
|
||||
if(!m_name)
|
||||
return;
|
||||
if(name.IsEmpty())
|
||||
{
|
||||
m_name->SetVisibility(ESlateVisibility::Collapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(name.Len() > 16)
|
||||
{
|
||||
name = name.Left(13) + "...";
|
||||
}
|
||||
m_name->SetText(FText::FromString(name));
|
||||
m_name->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
}
|
||||
}
|
||||
53
Source/UnrealProject/GUI/HUD/HealthBar.h
Normal file
53
Source/UnrealProject/GUI/HUD/HealthBar.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "HealthBar.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class EMinimapIcon : uint8
|
||||
{
|
||||
None = 0,
|
||||
Crown,
|
||||
MiniBoss,
|
||||
Dot,
|
||||
Camp,
|
||||
Player
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UHealthBar : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UHealthBar(const FObjectInitializer& init);
|
||||
virtual void NativeConstruct() override;
|
||||
virtual void NativeDestruct() override;
|
||||
|
||||
// Icon ID's
|
||||
// 0 = nothing
|
||||
// 1 = Crown
|
||||
// 2 = Mini-Boss
|
||||
// 3 = Dot
|
||||
// 4 = Camp
|
||||
// 5 = PlayerIcon
|
||||
void SetIcon(EMinimapIcon iconID);
|
||||
void SetStyle(int32 style);
|
||||
void UpdateHealth(int32 curr, int32 max);
|
||||
void UpdateMana(int32 curr, int32 max, float blocked = 0.0f);
|
||||
void UpdateAlignment(bool friendly);
|
||||
void SetName(FString name);
|
||||
|
||||
private:
|
||||
int32 m_style;
|
||||
bool m_friendly;
|
||||
class UWidgetSwitcher* m_styleSwitcher;
|
||||
class UStatBar* m_HP;
|
||||
class UStatBar* m_mana;
|
||||
class UStatBar* m_HP1;
|
||||
UTextBlock* m_name;
|
||||
UImage* m_icon;
|
||||
EMinimapIcon m_currentIcon;
|
||||
int32 m_updateCount = 0;
|
||||
};
|
||||
347
Source/UnrealProject/GUI/HUD/IngameHUD.cpp
Normal file
347
Source/UnrealProject/GUI/HUD/IngameHUD.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "DefaultPlayerController.h"
|
||||
#include "IngameHUD.h"
|
||||
#include "AbilityInfo.h"
|
||||
#include "AbilityState.h"
|
||||
#include "NetworkPlayer.h"
|
||||
#include "HealthBar.h"
|
||||
#include "CreatureSpawn.h"
|
||||
#include "PlayerSlot.h"
|
||||
#include "DefaultGameState.h"
|
||||
#include "DefaultPlayerState.h"
|
||||
#include "MiniMapWidget.h"
|
||||
#include "ToolTipWidget.h"
|
||||
#include "CombatText/CombatTextWidget.h"
|
||||
#include "SpellInfoDisplay.h"
|
||||
#include "ButtonBarSwitcher.h"
|
||||
#include "BaseSkillObject.h"
|
||||
#include "WidgetLayoutLibrary.h"
|
||||
#include "NetworkGhost.h"
|
||||
#include "TouhouBoss.h"
|
||||
#include "MiniBossCreature.h"
|
||||
#include "StatBar.h"
|
||||
#include <algorithm>
|
||||
|
||||
static UClass* healthBarWidgetClass;
|
||||
static UClass* playerSlotWidgetClass;
|
||||
|
||||
UIngameHUD::UIngameHUD(const FObjectInitializer& init)
|
||||
:Super(init)
|
||||
{
|
||||
ConstructorHelpers::FClassFinder<UHealthBar> HealthBarWidgetCF(TEXT("/Game/Assets/GUI/WEEGEE_HealthBar"));
|
||||
healthBarWidgetClass = HealthBarWidgetCF.Class;
|
||||
|
||||
miniMap = nullptr;
|
||||
}
|
||||
|
||||
void UIngameHUD::NativeConstruct()
|
||||
{
|
||||
m_myTeam = 0;
|
||||
m_character = nullptr;
|
||||
Super::NativeConstruct();
|
||||
|
||||
m_spellInfoDisplay = Cast<USpellInfoDisplay>(WidgetTree->FindWidget("SpellInfoDisplay"));
|
||||
miniMap = Cast<UMiniMapWidget>(WidgetTree->FindWidget("Minimap"));
|
||||
toolTips = Cast<UToolTipWidget>(WidgetTree->FindWidget("ToolTipLayer"));
|
||||
combatText = Cast<UCombatTextWidget>(WidgetTree->FindWidget("CombatTextLayer"));
|
||||
buttonBarSwitcher = Cast<UButtonBarSwitcher>(WidgetTree->FindWidget("ButtonBarSwitcher"));
|
||||
healthBarLayer = Cast<UCanvasPanel>(WidgetTree->FindWidget("HealthBarLayer"));
|
||||
|
||||
// Find stat display items
|
||||
m_playerStatDisplay.hpBar = Cast<UStatBar>(WidgetTree->FindWidget("HP"));
|
||||
m_playerStatDisplay.manaBar = Cast<UStatBar>(WidgetTree->FindWidget("Mana"));
|
||||
m_playerStatDisplay.expBar = Cast<UExperienceBar>(WidgetTree->FindWidget("Exp"));
|
||||
m_allyStatDisplay.hpBar = Cast<UStatBar>(WidgetTree->FindWidget("HP1"));
|
||||
m_allyStatDisplay.manaBar = Cast<UStatBar>(WidgetTree->FindWidget("Mana1"));
|
||||
m_allyStatDisplay.name = Cast<UTextBlock>(WidgetTree->FindWidget("Name1"));
|
||||
m_InitStatDisplay(m_playerStatDisplay);
|
||||
m_InitStatDisplay(m_allyStatDisplay);
|
||||
|
||||
check(healthBarLayer);
|
||||
}
|
||||
void UIngameHUD::NativeDestruct()
|
||||
{
|
||||
Super::NativeDestruct();
|
||||
}
|
||||
void UIngameHUD::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
||||
{
|
||||
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||
auto p = m_healthBars.CreateIterator();
|
||||
while (p)
|
||||
{
|
||||
m_UpdateHealthBar(p.Key(), p.Value());
|
||||
++p;
|
||||
}
|
||||
|
||||
ADefaultPlayerState* ps = Cast<ADefaultPlayerState>(GetOwningPlayer()->PlayerState);
|
||||
if (IsValid(ps))
|
||||
{
|
||||
m_UpdateStatDisplay(ps, m_playerStatDisplay);
|
||||
m_UpdateStatDisplay(ps->teamMate, m_allyStatDisplay);
|
||||
}
|
||||
|
||||
//UWorld* world = GetWorld();
|
||||
//check(world);
|
||||
//ADefaultGameState* state = Cast<ADefaultGameState>(world->GetGameState());
|
||||
}
|
||||
|
||||
void UIngameHUD::NativeOnAssignCharacter(class ANetworkPossessable* pawn /*= nullptr*/, TArray<FIngameSkillTreeSkill> skillsetPrototype /*= TArray<FIngameSkillTreeSkill>()*/)
|
||||
{
|
||||
m_character = pawn;
|
||||
|
||||
// Cast to ghost or player
|
||||
ANetworkPlayer* player = Cast<ANetworkPlayer>(pawn);
|
||||
ANetworkGhost* ghost = Cast<ANetworkGhost>(pawn);
|
||||
if(ghost)
|
||||
{
|
||||
// Grey out buttons in ghost mode
|
||||
buttonBarSwitcher->SetGlobalEnable(false);
|
||||
}
|
||||
else if(player)
|
||||
{
|
||||
// Enable buttons back in player mode
|
||||
buttonBarSwitcher->SetGlobalEnable(true);
|
||||
|
||||
// Set skill prototypes
|
||||
if(buttonBarSwitcher)
|
||||
{
|
||||
for(int32 i = 0; i < skillsetPrototype.Num(); i++)
|
||||
{
|
||||
// Don't assign buttons for passive skills
|
||||
if(skillsetPrototype[i].selectedEffect->passive)
|
||||
continue;
|
||||
|
||||
switch(skillsetPrototype[i].abilityType)
|
||||
{
|
||||
case 0:
|
||||
buttonBarSwitcher->AssignSkillButton(skillsetPrototype[i], false);
|
||||
break;
|
||||
case 1:
|
||||
buttonBarSwitcher->AssignSkillButton(skillsetPrototype[i], true);
|
||||
break;
|
||||
case 2:
|
||||
if(skillsetPrototype[i].selectedEffect && !skillsetPrototype[i].selectedEffect->passive)
|
||||
{
|
||||
GERROR("Non-passive skill added to skill with shape type == passive, " +
|
||||
skillsetPrototype[i].skillObject->GetName() + " <= " +
|
||||
skillsetPrototype[i].selectedEffect->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_myTeam = player->GetTeam();
|
||||
}
|
||||
|
||||
OnAssignCharacter(pawn);
|
||||
}
|
||||
|
||||
void UIngameHUD::OnLevelUp(TArray<FIngameSkillTreeSkill> updatedSkills)
|
||||
{
|
||||
if (m_spellInfoDisplay && GetPlayer())
|
||||
m_spellInfoDisplay->OnLevelUp(GetPlayer(), updatedSkills);
|
||||
|
||||
if (buttonBarSwitcher)
|
||||
{
|
||||
for (int32 i = 0; i < updatedSkills.Num(); i++)
|
||||
{
|
||||
buttonBarSwitcher->SetSkillButtonEnabled(updatedSkills[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIngameHUD::UpdateCooldowns(TArray<class AAbilityState*> abilityStates, ANetworkPlayer* player)
|
||||
{
|
||||
if (buttonBarSwitcher)
|
||||
buttonBarSwitcher->UpdateCooldowns(abilityStates, player);
|
||||
}
|
||||
|
||||
void UIngameHUD::OnCharacterCreated(ANetworkCharacter* character)
|
||||
{
|
||||
if (m_healthBars.Find(character))
|
||||
{
|
||||
// When OnCharacterCreated is called twice
|
||||
GWWARNING(L"OnCharacterCreated called more thatn once");
|
||||
return;
|
||||
}
|
||||
UHealthBar* widget = CreateWidget<UHealthBar>(GetOwningPlayer(), healthBarWidgetClass);
|
||||
check(widget);
|
||||
healthBarLayer->AddChild(widget);
|
||||
m_healthBars.Add(character, widget);
|
||||
m_UpdateHealthBar(character, widget);
|
||||
}
|
||||
void UIngameHUD::OnCharacterDestroyed(ANetworkCharacter* character)
|
||||
{
|
||||
auto it = m_healthBars.Find(character);
|
||||
if (it)
|
||||
{
|
||||
(*it)->RemoveFromViewport();
|
||||
m_healthBars.Remove(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
// When OnCharacterDestroyed is called twice
|
||||
GWWARNING(L"OnCharacterDestroyed called more than once");
|
||||
}
|
||||
}
|
||||
|
||||
ANetworkPlayer* UIngameHUD::GetTeamMate() const
|
||||
{
|
||||
if (Cast<ANetworkPlayer>(m_character))
|
||||
{
|
||||
ANetworkPlayer* teamMate = Cast<ANetworkPlayer>(m_character)->GetTeamMate();
|
||||
return teamMate;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
ANetworkPlayer* UIngameHUD::GetPlayer() const
|
||||
{
|
||||
return Cast<ANetworkPlayer>(m_character);
|
||||
}
|
||||
ANetworkGhost* UIngameHUD::GetGhost() const
|
||||
{
|
||||
return Cast<ANetworkGhost>(m_character);
|
||||
}
|
||||
|
||||
class ADefaultPlayerState* UIngameHUD::GetPlayerState() const
|
||||
{
|
||||
if (!m_character)
|
||||
return nullptr;
|
||||
return Cast<ADefaultPlayerState>(m_character->PlayerState);
|
||||
}
|
||||
|
||||
void UIngameHUD::m_UpdateHealthBar(class ANetworkCharacter* character, class UHealthBar* bar)
|
||||
{
|
||||
APlayerController* pc = GetOwningPlayer();
|
||||
if (!IsValid(pc)) return;
|
||||
|
||||
FVector screenPos;
|
||||
const float height = character->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
|
||||
const FVector position = character->GetActorLocation();
|
||||
const FVector worldLocation = FVector(position.X, position.Y, position.Z + height);
|
||||
|
||||
// Check if is approximately in camera view
|
||||
const FVector forward = pc->PlayerCameraManager->GetCameraRotation().RotateVector(FVector(1.0f, 0.0f, 0.0f));
|
||||
const FVector dir = (worldLocation - pc->PlayerCameraManager->GetCameraLocation()).GetSafeNormal();
|
||||
float dot = FVector::DotProduct(forward, dir);
|
||||
if (dot < 0.01f)
|
||||
{
|
||||
bar->SetVisibility(ESlateVisibility::Hidden);
|
||||
return;
|
||||
}
|
||||
bar->SetVisibility(ESlateVisibility::Visible);
|
||||
|
||||
pc->ProjectWorldLocationToScreenWithDistance(FVector(position.X, position.Y, position.Z + height), screenPos);
|
||||
const float viewportScale = UWidgetLayoutLibrary::GetViewportScale(healthBarLayer);
|
||||
|
||||
uint32 otherTeam = character->GetTeam();
|
||||
|
||||
// Check witch bar style to use
|
||||
bool useExtendedBarStyle = character->playerName.Len() > 0;
|
||||
if(useExtendedBarStyle)
|
||||
{
|
||||
bar->SetStyle(0);
|
||||
bar->UpdateMana(character->GetMana(), character->GetMaxMana(), character->GetBlockedMana());
|
||||
bar->SetName(character->playerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
bar->SetStyle(1);
|
||||
bar->SetName("");
|
||||
}
|
||||
bar->UpdateAlignment(otherTeam == m_myTeam);
|
||||
bar->UpdateHealth(character->GetHealth(), character->GetMaxHealth());
|
||||
|
||||
// Set the icon next to the bar
|
||||
EMinimapIcon icon = EMinimapIcon::None;
|
||||
if(character->IsA<ATouhouBoss>())
|
||||
{
|
||||
icon = EMinimapIcon::Crown;
|
||||
}
|
||||
else if(character->IsA<AMiniBossCreature>())
|
||||
{
|
||||
icon = EMinimapIcon::MiniBoss;
|
||||
}
|
||||
bar->SetIcon(icon);
|
||||
|
||||
// Set the on-screen position
|
||||
UCanvasPanelSlot* asSlot = Cast<UCanvasPanelSlot>(bar->Slot);
|
||||
if (IsValid(asSlot))
|
||||
{
|
||||
asSlot->SetAutoSize(true);
|
||||
asSlot->SetAlignment(FVector2D(0.5f, 1));
|
||||
const FVector2D setPos = FVector2D(screenPos.X, screenPos.Y) / viewportScale;
|
||||
asSlot->SetPosition(FVector2D(FPlatformMath::RoundToFloat(setPos.X), FPlatformMath::RoundToFloat(setPos.Y)));
|
||||
}
|
||||
}
|
||||
|
||||
void UIngameHUD::m_UpdateStatDisplay(class ADefaultPlayerState* state, const FStatDisplay& sd)
|
||||
{
|
||||
ANetworkPlayer* player = state ? state->character : nullptr;
|
||||
if(sd.hpBar)
|
||||
{
|
||||
if(!player)
|
||||
sd.hpBar->SetStat(0.0f, true);
|
||||
else
|
||||
{
|
||||
sd.hpBar->SetStat(player->GetHealth(), player->GetMaxHealth(), true);
|
||||
}
|
||||
}
|
||||
if(sd.manaBar)
|
||||
{
|
||||
if(!player)
|
||||
{
|
||||
sd.manaBar->SetBlocked(0.0f);
|
||||
sd.manaBar->SetStat(0, 1, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
sd.manaBar->SetStat(player->GetMana(), player->GetMaxMana(), true);
|
||||
sd.manaBar->SetBlocked((float)player->GetBlockedMana() / (float)player->GetMaxMana());
|
||||
}
|
||||
}
|
||||
|
||||
if(sd.expBar)
|
||||
{
|
||||
if(state)
|
||||
{
|
||||
if(state->GetLevel() == state->GetMaxLevel())
|
||||
sd.expBar->Update(1.0f, state->GetMaxLevel(), true);
|
||||
else
|
||||
sd.expBar->Update((float)state->GetExperience() / (float)state->GetExperienceToLevel(), state->GetLevel(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
sd.expBar->Update(0.0f, 0, false);
|
||||
}
|
||||
}
|
||||
if(sd.name)
|
||||
{
|
||||
if(state)
|
||||
{
|
||||
state->UpdatePersona();
|
||||
sd.name->SetText(FText::FromString(state->nickname));
|
||||
}
|
||||
else
|
||||
{
|
||||
sd.name->SetText(FText());
|
||||
}
|
||||
}
|
||||
if(sd.avatar && state)
|
||||
{
|
||||
sd.avatar->SetBrushFromTexture(state->avatar);
|
||||
}
|
||||
}
|
||||
|
||||
void UIngameHUD::m_InitStatDisplay(const FStatDisplay& sd)
|
||||
{
|
||||
if(sd.hpBar)
|
||||
{
|
||||
sd.hpBar->SetBarColor(EBarColor::GreenGradient);
|
||||
}
|
||||
if(sd.manaBar)
|
||||
{
|
||||
sd.manaBar->SetBarColor(EBarColor::BlueGradient);
|
||||
}
|
||||
}
|
||||
93
Source/UnrealProject/GUI/HUD/IngameHUD.h
Normal file
93
Source/UnrealProject/GUI/HUD/IngameHUD.h
Normal file
@@ -0,0 +1,93 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "IngameSkillTree.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "IngameHUD.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UExperienceBar : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintImplementableEvent)
|
||||
void Update(float rate, int32 level, bool max);
|
||||
};
|
||||
|
||||
struct FStatDisplay
|
||||
{
|
||||
class UStatBar* hpBar;
|
||||
class UStatBar* manaBar;
|
||||
class UExperienceBar* expBar;
|
||||
class UImage* avatar;
|
||||
class UTextBlock* name;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UIngameHUD : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UIngameHUD(const FObjectInitializer& init);
|
||||
virtual void NativeConstruct() override;
|
||||
virtual void NativeDestruct() override;
|
||||
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||
|
||||
// Sets the player owned character
|
||||
void NativeOnAssignCharacter(class ANetworkPossessable* pawn = nullptr, TArray<FIngameSkillTreeSkill> skillsetPrototype = TArray<FIngameSkillTreeSkill>());
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "HUD")
|
||||
void OnAssignCharacter(ANetworkPossessable* pawn);
|
||||
|
||||
// Called when the character levels up
|
||||
void OnLevelUp(TArray<FIngameSkillTreeSkill> updatedSkills);
|
||||
|
||||
// Updates the displayed cooldowns in the UI with the provided ability states
|
||||
void UpdateCooldowns(TArray<class AAbilityState*> abilityStates, class ANetworkPlayer* player);
|
||||
|
||||
// Called when a character spawns
|
||||
// this makes it display a health-bar in the HUD
|
||||
void OnCharacterCreated(class ANetworkCharacter* character);
|
||||
// Called when a character despawns(destroyed, killed)
|
||||
// this removes all the health-bars, etc. for this character
|
||||
void OnCharacterDestroyed(class ANetworkCharacter* character);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "UI")
|
||||
class ANetworkPlayer* GetTeamMate() const;
|
||||
UFUNCTION(BlueprintCallable, Category = "UI")
|
||||
class ANetworkPlayer* GetPlayer() const;
|
||||
UFUNCTION(BlueprintCallable, Category = "UI")
|
||||
class ANetworkGhost* GetGhost() const;
|
||||
UFUNCTION(BlueprintCallable, Category = "UI")
|
||||
class ADefaultPlayerState* GetPlayerState() const;
|
||||
|
||||
class UMiniMapWidget* miniMap;
|
||||
class UToolTipWidget* toolTips;
|
||||
class UCombatTextWidget* combatText;
|
||||
class UButtonBarSwitcher* buttonBarSwitcher;
|
||||
class UCanvasPanel* healthBarLayer;
|
||||
|
||||
private:
|
||||
// This updates an on screen health bar for a given network character
|
||||
void m_UpdateHealthBar(class ANetworkCharacter* character, class UHealthBar* bar);
|
||||
void m_UpdateStatDisplay(class ADefaultPlayerState* player, const FStatDisplay& statDisplay);
|
||||
void m_InitStatDisplay(const FStatDisplay& statDisplay);
|
||||
|
||||
FStatDisplay m_playerStatDisplay;
|
||||
FStatDisplay m_allyStatDisplay;
|
||||
|
||||
// Maps every character in the game to a health bar widget on-screen
|
||||
UPROPERTY()
|
||||
TMap<class ANetworkCharacter*, class UHealthBar*> m_healthBars;
|
||||
|
||||
UPROPERTY()
|
||||
class ANetworkPossessable* m_character;
|
||||
UPROPERTY()
|
||||
class USpellInfoDisplay* m_spellInfoDisplay;
|
||||
|
||||
uint32 m_myTeam;
|
||||
};
|
||||
13
Source/UnrealProject/GUI/HUD/KOTHHUD.cpp
Normal file
13
Source/UnrealProject/GUI/HUD/KOTHHUD.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "KOTHHUD.h"
|
||||
|
||||
|
||||
void UKOTHHUD::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
}
|
||||
void UKOTHHUD::Update(TArray<FKOTHTeamState> teamStates)
|
||||
{
|
||||
}
|
||||
16
Source/UnrealProject/GUI/HUD/KOTHHUD.h
Normal file
16
Source/UnrealProject/GUI/HUD/KOTHHUD.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "KOTHTeamState.h"
|
||||
#include "KOTHHUD.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UKOTHHUD : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
void NativeConstruct() override;
|
||||
void Update(TArray<FKOTHTeamState> teamStates);
|
||||
};
|
||||
14
Source/UnrealProject/GUI/HUD/KeyDisplay.cpp
Normal file
14
Source/UnrealProject/GUI/HUD/KeyDisplay.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "KeyDisplay.h"
|
||||
|
||||
void UKeyDisplay::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
}
|
||||
|
||||
void UKeyDisplay::NativeDestruct()
|
||||
{
|
||||
Super::NativeDestruct();
|
||||
}
|
||||
16
Source/UnrealProject/GUI/HUD/KeyDisplay.h
Normal file
16
Source/UnrealProject/GUI/HUD/KeyDisplay.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "KeyDisplay.generated.h"
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UKeyDisplay : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void NativeConstruct() override;
|
||||
virtual void NativeDestruct() override;
|
||||
};
|
||||
192
Source/UnrealProject/GUI/HUD/StatBar.cpp
Normal file
192
Source/UnrealProject/GUI/HUD/StatBar.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "StatBar.h"
|
||||
|
||||
static UTexture2D* barTextures[6];
|
||||
static FLinearColor barColors[4];
|
||||
static UMaterial* textureBarMaterialClass;
|
||||
|
||||
UStatBar::UStatBar(const FObjectInitializer& init) : Super(init)
|
||||
{
|
||||
textureBarMaterialClass = ConstructorHelpers::FObjectFinder<UMaterial>(L"/Game/Assets/Art/UI/M_HealthBar2.M_HealthBar2").Object;
|
||||
|
||||
barColors[0] = FLinearColor::Green * 0.5f;
|
||||
barColors[1] = FLinearColor::Red * 0.6f;
|
||||
barColors[2] = FLinearColor::Blue * 0.8f;
|
||||
barColors[3] = FLinearColor(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
barTextures[0] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/HealthBar/UI_MainStatusBarHealth").Object;
|
||||
barTextures[1] = ConstructorHelpers::FObjectFinder<UTexture2D>(L"/Game/Assets/Art/UI/HealthBar/UI_MainStatusBarMana").Object;
|
||||
|
||||
m_lastValue = 1.0f;
|
||||
m_currentValue = 1.0f;
|
||||
damageAnimationDuration = 0.3f;
|
||||
m_damageAnimation = 0.0f;
|
||||
showText = false;
|
||||
}
|
||||
|
||||
void UStatBar::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
m_base = Cast<UImage>(WidgetTree->FindWidget("Base"));
|
||||
m_blocked = Cast<UImage>(WidgetTree->FindWidget("Blocked"));
|
||||
m_damage = Cast<UImage>(WidgetTree->FindWidget("Damage"));
|
||||
m_text = Cast<UTextBlock>(WidgetTree->FindWidget("BarText"));
|
||||
if(m_damage)
|
||||
{
|
||||
m_damage->SetVisibility(ESlateVisibility::Hidden);
|
||||
UMaterialInstanceDynamic* damageMat = m_damage->GetDynamicMaterial();
|
||||
damageMat->SetScalarParameterValue("Brightness", 4.0f);
|
||||
}
|
||||
if(m_blocked)
|
||||
m_blocked->SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
||||
|
||||
#pragma optimize("", off)
|
||||
void UStatBar::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
||||
{
|
||||
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||
|
||||
if(m_damageAnimation > 0.0f && m_damage)
|
||||
{
|
||||
float r = m_damageAnimation / damageAnimationDuration;
|
||||
float damageSize = (m_currentValue - m_lastValue);
|
||||
|
||||
UMaterialInstanceDynamic* matDamage = m_damage->GetDynamicMaterial();
|
||||
if(damageSize < 0.0f)
|
||||
{
|
||||
damageSize *= (1.0f - r);
|
||||
matDamage->SetScalarParameterValue("Start", m_currentValue);
|
||||
matDamage->SetScalarParameterValue("End", m_lastValue + damageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
damageSize *= (1.0f-r);
|
||||
matDamage->SetScalarParameterValue("Start", m_lastValue + damageSize);
|
||||
matDamage->SetScalarParameterValue("End", m_currentValue);
|
||||
}
|
||||
|
||||
m_damageAnimation -= InDeltaTime;
|
||||
if(m_damageAnimation <= 0.0f)
|
||||
{
|
||||
m_damageAnimation = 0.0f;
|
||||
m_damage->SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma optimize("", off)
|
||||
void UStatBar::SetStat(float newStat, bool applyAnimation)
|
||||
{
|
||||
if(!m_base)
|
||||
return;
|
||||
if(newStat == m_currentValue)
|
||||
return;
|
||||
|
||||
float delta = newStat - m_currentValue;
|
||||
if(delta != 0 && m_damageAnimation > 0.0f)
|
||||
{
|
||||
// Append animation
|
||||
float r = m_damageAnimation / damageAnimationDuration;
|
||||
float damageSize = (m_currentValue - m_lastValue);
|
||||
if(damageSize < 0.0f)
|
||||
damageSize *= (1.0f - r);
|
||||
else
|
||||
damageSize *= (1.0f - r);
|
||||
delta += damageSize;
|
||||
m_lastValue = m_lastValue + damageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastValue = m_currentValue;
|
||||
}
|
||||
m_currentValue = newStat;
|
||||
|
||||
// Apply animation
|
||||
if(delta != 0.0f && applyAnimation && m_damage)
|
||||
{
|
||||
const FLinearColor deltaColor = FLinearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
m_damageAnimation = damageAnimationDuration;
|
||||
|
||||
UMaterialInstanceDynamic* matDamage = m_base->GetDynamicMaterial();
|
||||
if(delta < 0.0f)
|
||||
{
|
||||
matDamage->SetScalarParameterValue("Start", newStat);
|
||||
matDamage->SetScalarParameterValue("End", m_lastValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
matDamage->SetScalarParameterValue("Start", m_lastValue);
|
||||
matDamage->SetScalarParameterValue("End", newStat);
|
||||
}
|
||||
m_damage->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
}
|
||||
|
||||
UMaterialInstanceDynamic* matBase = m_base->GetDynamicMaterial();
|
||||
matBase->SetScalarParameterValue("Start", 0.0f);
|
||||
matBase->SetScalarParameterValue("End", newStat);
|
||||
}
|
||||
|
||||
void UStatBar::SetStat(int32 newStat, int32 max, bool applyAnimation)
|
||||
{
|
||||
if(showText && m_text)
|
||||
{
|
||||
FText t = FText::FromString(FString::Printf(L"%d / %d", newStat, max));
|
||||
m_text->SetText(t);
|
||||
m_text->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_text->SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
||||
|
||||
float r = (float)newStat / (float)max;
|
||||
SetStat(r, applyAnimation);
|
||||
}
|
||||
|
||||
void UStatBar::SetBlocked(float newBlocked)
|
||||
{
|
||||
if(!m_blocked)
|
||||
return;
|
||||
UMaterialInstanceDynamic* mat = m_blocked->GetDynamicMaterial();
|
||||
if(newBlocked > 0.0f)
|
||||
{
|
||||
mat->SetScalarParameterValue("Start", 1.0f - newBlocked);
|
||||
mat->SetScalarParameterValue("End", 1.0f);
|
||||
m_blocked->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blocked->SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
||||
}
|
||||
|
||||
void UStatBar::SetBarColor(EBarColor _colorID)
|
||||
{
|
||||
int32 colorID = (int32)_colorID;
|
||||
if(!m_base)
|
||||
return;
|
||||
|
||||
if((colorID & 0x80) != 0)
|
||||
{
|
||||
colorID = colorID & 0x7F;
|
||||
colorID = FMath::Clamp(colorID, 0, (int32)(sizeof(barTextures) / sizeof(UTexture2D*)));
|
||||
|
||||
m_base->SetBrushFromMaterial(textureBarMaterialClass);
|
||||
m_blocked->SetBrushFromMaterial(textureBarMaterialClass);
|
||||
m_damage->SetBrushFromMaterial(textureBarMaterialClass);
|
||||
UMaterialInstanceDynamic* baseMat = m_base->GetDynamicMaterial();
|
||||
baseMat->SetTextureParameterValue("Texture", barTextures[colorID]);
|
||||
baseMat = m_damage->GetDynamicMaterial();
|
||||
baseMat->SetTextureParameterValue("Texture", barTextures[colorID]);
|
||||
baseMat = m_blocked->GetDynamicMaterial();
|
||||
baseMat->SetTextureParameterValue("Texture", barTextures[colorID]);
|
||||
}
|
||||
else
|
||||
{
|
||||
colorID = FMath::Clamp(colorID, 0, (int32)(sizeof(barColors) / sizeof(FLinearColor)));
|
||||
|
||||
UMaterialInstanceDynamic* baseMat = m_base->GetDynamicMaterial();
|
||||
baseMat->SetVectorParameterValue("Color", barColors[colorID]);
|
||||
}
|
||||
}
|
||||
49
Source/UnrealProject/GUI/HUD/StatBar.h
Normal file
49
Source/UnrealProject/GUI/HUD/StatBar.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "StatBar.generated.h"
|
||||
|
||||
enum class EBarColor
|
||||
{
|
||||
Green = 0,
|
||||
Red,
|
||||
Blue,
|
||||
Purple,
|
||||
GreenGradient = 0x80,
|
||||
BlueGradient
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UStatBar : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UStatBar(const FObjectInitializer& init);
|
||||
void NativeConstruct() override;
|
||||
void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||
|
||||
void SetStat(int32 newStat, int32 max, bool applyAnimation);
|
||||
void SetStat(float newStat, bool applyAnimation);
|
||||
void SetBlocked(float newBlocked);
|
||||
void SetBarColor(EBarColor colorID);
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Stat Bar")
|
||||
float damageAnimationDuration;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stat Bar")
|
||||
bool showText;
|
||||
|
||||
private:
|
||||
float m_damageAnimation;
|
||||
float m_lastValue;
|
||||
float m_currentValue;
|
||||
UImage* m_base;
|
||||
UImage* m_blocked;
|
||||
UImage* m_damage;
|
||||
UTextBlock* m_text;
|
||||
};
|
||||
49
Source/UnrealProject/GUI/HUD/Timer.cpp
Normal file
49
Source/UnrealProject/GUI/HUD/Timer.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#include "UnrealProject.h"
|
||||
#include "Timer.h"
|
||||
#include "Kismet/KismetStringLibrary.h"
|
||||
|
||||
void UTimer::NativeConstruct()
|
||||
{
|
||||
m_duration = 0.0f;
|
||||
m_text = Cast<UTextBlock>(WidgetTree->FindWidget("Text"));
|
||||
m_timerText = Cast<UTextBlock>(WidgetTree->FindWidget("Time"));
|
||||
m_clock = Cast<UImage>(WidgetTree->FindWidget("Klokje"));
|
||||
if(!m_text)
|
||||
GWARNING("No \"Text\" text widget found in " + GetName());
|
||||
if(!m_text)
|
||||
GWARNING("No \"Time\" text widget found in " + GetName());
|
||||
if(!m_clock)
|
||||
GWARNING("No \"Klokje\" image widget found in " + GetName());
|
||||
Super::NativeConstruct();
|
||||
}
|
||||
|
||||
void UTimer::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
||||
{
|
||||
m_time = FMath::Clamp(m_time - InDeltaTime, 0.0f, m_duration);
|
||||
if(m_duration == 0.0f)
|
||||
OnSetTimer(0.0f);
|
||||
else
|
||||
OnSetTimer(m_time / m_duration);
|
||||
|
||||
if(m_timerText)
|
||||
{
|
||||
FString msg = UKismetStringLibrary::TimeSecondsToString(m_time);
|
||||
m_timerText->SetText(FText::FromString(msg));
|
||||
}
|
||||
|
||||
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||
}
|
||||
|
||||
void UTimer::SetTimer(float duration, bool reset)
|
||||
{
|
||||
m_duration = duration;
|
||||
if(reset)
|
||||
m_time = duration;
|
||||
}
|
||||
void UTimer::SetText(const FString& text)
|
||||
{
|
||||
if(m_text)
|
||||
m_text->SetText(FText::FromString(text));
|
||||
}
|
||||
44
Source/UnrealProject/GUI/HUD/Timer.h
Normal file
44
Source/UnrealProject/GUI/HUD/Timer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Project Lab - NHTV Igad
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "Timer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALPROJECT_API UTimer : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Calbacks handling timer changes
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "HUDTimer")
|
||||
void OnSetTimer(float rate);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "HUDTimer")
|
||||
void OnHide(); // Play animation
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "HUDTimer")
|
||||
void OnShow(); // Play animation
|
||||
|
||||
void NativeConstruct();
|
||||
void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HUDTimer")
|
||||
void SetTimer(float duration, bool reset = true);
|
||||
UFUNCTION(BlueprintCallable, Category = "HUDTimer")
|
||||
void SetText(const FString& text);
|
||||
UFUNCTION(BlueprintCallable, Category = "HUDTimer")
|
||||
float GetTime() const
|
||||
{
|
||||
return m_time;
|
||||
}
|
||||
|
||||
private:
|
||||
float m_time;
|
||||
float m_duration;
|
||||
UImage* m_clock;
|
||||
UTextBlock* m_text;
|
||||
UTextBlock* m_timerText;
|
||||
};
|
||||
Reference in New Issue
Block a user