Compare commits
2 Commits
65edf1081b
...
ede49c1777
| Author | SHA1 | Date | |
|---|---|---|---|
| ede49c1777 | |||
| 484c8d5d4f |
BIN
Content/ZMMO/Data/UI/DT_UI_VitalsReadout.uasset
Normal file
BIN
Content/ZMMO/Data/UI/DT_UI_VitalsReadout.uasset
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,21 +1,33 @@
|
|||||||
#include "ZMMOHudPlayerVitalsWidget.h"
|
#include "ZMMOHudPlayerVitalsWidget.h"
|
||||||
|
|
||||||
|
#include "Components/RichTextBlock.h"
|
||||||
#include "Components/TextBlock.h"
|
#include "Components/TextBlock.h"
|
||||||
#include "UI/Widgets/UIProgressBar_Base.h"
|
#include "UI/Widgets/UIProgressBar_Base.h"
|
||||||
#include "Internationalization/Text.h"
|
#include "Internationalization/Text.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/** Formata int com separador de milhar do locale (ex.: 9840 -> "9,840"). */
|
|
||||||
FText FormatNumber(int64 Value)
|
|
||||||
{
|
|
||||||
return FText::AsNumber(Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
float SafeRatio(int32 Current, int32 Max)
|
float SafeRatio(int32 Current, int32 Max)
|
||||||
{
|
{
|
||||||
return Max > 0 ? FMath::Clamp(static_cast<float>(Current) / static_cast<float>(Max), 0.f, 1.f) : 0.f;
|
return Max > 0 ? FMath::Clamp(static_cast<float>(Current) / static_cast<float>(Max), 0.f, 1.f) : 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Ratio 0..1 pras barras de EXP/JOB (int64). ToNext<=0 = cap -> barra cheia. */
|
||||||
|
float ExpRatio(int64 Cur, int64 ToNext)
|
||||||
|
{
|
||||||
|
return ToNext > 0
|
||||||
|
? FMath::Clamp(static_cast<float>(static_cast<double>(Cur) / static_cast<double>(ToNext)), 0.f, 1.f)
|
||||||
|
: 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Readout de progressao em "%": numero (Default) + "%" (unit/cinza).
|
||||||
|
* Cap (ToNext<=0) -> "MAX". Markup resolve no DT_UI_VitalsReadout. */
|
||||||
|
FText ExpReadoutText(int64 Cur, int64 ToNext)
|
||||||
|
{
|
||||||
|
if (ToNext <= 0) { return FText::FromString(TEXT("MAX")); }
|
||||||
|
const double Pct = static_cast<double>(Cur) / static_cast<double>(ToNext) * 100.0;
|
||||||
|
return FText::FromString(FString::Printf(TEXT("%.2f<unit>%%</>"), Pct));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Snapshot)
|
void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Snapshot)
|
||||||
@@ -25,21 +37,31 @@ void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Sn
|
|||||||
// HP / SP (pool efetivo — % real)
|
// HP / SP (pool efetivo — % real)
|
||||||
ApplyHpSp(Snapshot.Hp, Snapshot.MaxHp, Snapshot.Sp, Snapshot.MaxSp);
|
ApplyHpSp(Snapshot.Hp, Snapshot.MaxHp, Snapshot.Sp, Snapshot.MaxSp);
|
||||||
|
|
||||||
// Level
|
// Level — markup: "LVL " (pct/cinza) + número (num/gold-bright maior)
|
||||||
if (LvlText)
|
if (LvlText)
|
||||||
{
|
{
|
||||||
LvlText->SetText(FText::FromString(FString::Printf(TEXT("LVL %d"), Snapshot.BaseLevel)));
|
LvlText->SetText(FText::FromString(
|
||||||
|
FString::Printf(TEXT("<pct>LVL </><num>%d</>"), Snapshot.BaseLevel)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BASE / JOB EXP — sem "exp-to-next" no snapshot. Readout mostra valor
|
// BASE / JOB EXP — barras em % (exp atual / exp-to-next, resolvido pelo
|
||||||
// absoluto acumulado; as barras ficam pra quando a curva de exp existir.
|
// server via JobsDatabase). Em cap (ToNext=0) a barra enche e o readout
|
||||||
|
// vira "MAX". Readout exibe a porcentagem (numero + "%" cinza).
|
||||||
|
if (ExpBar)
|
||||||
|
{
|
||||||
|
ExpBar->SetTargetPrimaryLevel(ExpRatio(Snapshot.BaseExp, Snapshot.BaseExpToNext));
|
||||||
|
}
|
||||||
|
if (JobBar)
|
||||||
|
{
|
||||||
|
JobBar->SetTargetPrimaryLevel(ExpRatio(Snapshot.JobExp, Snapshot.JobExpToNext));
|
||||||
|
}
|
||||||
if (ExpReadout)
|
if (ExpReadout)
|
||||||
{
|
{
|
||||||
ExpReadout->SetText(FormatNumber(Snapshot.BaseExp));
|
ExpReadout->SetText(ExpReadoutText(Snapshot.BaseExp, Snapshot.BaseExpToNext));
|
||||||
}
|
}
|
||||||
if (JobReadout)
|
if (JobReadout)
|
||||||
{
|
{
|
||||||
JobReadout->SetText(FormatNumber(Snapshot.JobExp));
|
JobReadout->SetText(ExpReadoutText(Snapshot.JobExp, Snapshot.JobExpToNext));
|
||||||
}
|
}
|
||||||
|
|
||||||
OnSnapshotApplied(Snapshot);
|
OnSnapshotApplied(Snapshot);
|
||||||
@@ -60,17 +82,20 @@ void UZMMOHudPlayerVitalsWidget::ApplyHpSp(int32 Hp, int32 MaxHp, int32 Sp, int3
|
|||||||
{
|
{
|
||||||
SpBar->SetTargetPrimaryLevel(SafeRatio(Sp, MaxSp));
|
SpBar->SetTargetPrimaryLevel(SafeRatio(Sp, MaxSp));
|
||||||
}
|
}
|
||||||
|
// Markup RichText: atual (Default/branco) + "/" (sep/escuro) + max (max/cinza).
|
||||||
|
// Tags resolvem no DT_UI_VitalsReadout (TextStyleSet do RichTextBlock).
|
||||||
|
auto MakeReadout = [](int32 Cur, int32 Max) -> FText
|
||||||
|
{
|
||||||
|
return FText::FromString(FString::Printf(TEXT("%s<sep>/</><max>%s</>"),
|
||||||
|
*FText::AsNumber(Cur).ToString(), *FText::AsNumber(Max).ToString()));
|
||||||
|
};
|
||||||
if (HpReadout)
|
if (HpReadout)
|
||||||
{
|
{
|
||||||
HpReadout->SetText(FText::Format(
|
HpReadout->SetText(MakeReadout(Hp, MaxHp));
|
||||||
NSLOCTEXT("ZMMOHud", "HpSpReadout", "{0}/{1}"),
|
|
||||||
FormatNumber(Hp), FormatNumber(MaxHp)));
|
|
||||||
}
|
}
|
||||||
if (SpReadout)
|
if (SpReadout)
|
||||||
{
|
{
|
||||||
SpReadout->SetText(FText::Format(
|
SpReadout->SetText(MakeReadout(Sp, MaxSp));
|
||||||
NSLOCTEXT("ZMMOHud", "HpSpReadout", "{0}/{1}"),
|
|
||||||
FormatNumber(Sp), FormatNumber(MaxSp)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
class UUIProgressBar_Base;
|
class UUIProgressBar_Base;
|
||||||
class UTextBlock;
|
class UTextBlock;
|
||||||
|
class URichTextBlock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sub-widget do HUD: painel de vitais do player (portrait + nome/job/level +
|
* Sub-widget do HUD: painel de vitais do player (portrait + nome/job/level +
|
||||||
@@ -71,19 +72,19 @@ protected:
|
|||||||
TObjectPtr<UTextBlock> ClassText;
|
TObjectPtr<UTextBlock> ClassText;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
TObjectPtr<UTextBlock> LvlText;
|
TObjectPtr<URichTextBlock> LvlText;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
TObjectPtr<UTextBlock> HpReadout;
|
TObjectPtr<URichTextBlock> HpReadout;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
TObjectPtr<UTextBlock> SpReadout;
|
TObjectPtr<URichTextBlock> SpReadout;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
TObjectPtr<UTextBlock> ExpReadout;
|
TObjectPtr<URichTextBlock> ExpReadout;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
TObjectPtr<UTextBlock> JobReadout;
|
TObjectPtr<URichTextBlock> JobReadout;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Último snapshot recebido (cache pra ApplyHpSp manter MaxHp/MaxSp). */
|
/** Último snapshot recebido (cache pra ApplyHpSp manter MaxHp/MaxSp). */
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ namespace
|
|||||||
S.EntityId = P.EntityId;
|
S.EntityId = P.EntityId;
|
||||||
S.ClassId = P.ClassId;
|
S.ClassId = P.ClassId;
|
||||||
S.BaseLevel = P.BaseLevel;
|
S.BaseLevel = P.BaseLevel;
|
||||||
S.BaseExp = P.BaseExp;
|
S.BaseExp = P.BaseExp;
|
||||||
|
S.BaseExpToNext = P.BaseExpToNext;
|
||||||
S.JobLevel = P.JobLevel;
|
S.JobLevel = P.JobLevel;
|
||||||
S.JobExp = P.JobExp;
|
S.JobExp = P.JobExp;
|
||||||
|
S.JobExpToNext = P.JobExpToNext;
|
||||||
S.Str = P.Str;
|
S.Str = P.Str;
|
||||||
S.Agi = P.Agi;
|
S.Agi = P.Agi;
|
||||||
S.Vit = P.Vit;
|
S.Vit = P.Vit;
|
||||||
|
|||||||
@@ -26,8 +26,13 @@ struct ZMMOATTRIBUTES_API FZMMOAttributesSnapshot
|
|||||||
// === Progressao ===
|
// === Progressao ===
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 BaseLevel = 1;
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 BaseLevel = 1;
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 BaseExp = 0;
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 BaseExp = 0;
|
||||||
|
/** EXP pra subir o proximo base level (server resolve via JobsDatabase).
|
||||||
|
* 0 = ja' em cap -> barra cheia. % = BaseExp / BaseExpToNext. */
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 BaseExpToNext = 0;
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 JobLevel = 1;
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 JobLevel = 1;
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 JobExp = 0;
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 JobExp = 0;
|
||||||
|
/** EXP pra subir o proximo job level. 0 = ja' em cap -> barra cheia. */
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 JobExpToNext = 0;
|
||||||
|
|
||||||
// === Stats primarios (Camada 1 base; efetivos vao em derivados) ===
|
// === Stats primarios (Camada 1 base; efetivos vao em derivados) ===
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Str = 1;
|
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Str = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user