feat(ui/hud): barras EXP/JOB em % via exp-to-next do snapshot
FZMMOAttributesSnapshot ganha BaseExpToNext/JobExpToNext espelhando o wire do server. ApplySnapshot liga ExpBar/JobBar pelo ratio (exp / exp-to-next) e os readouts mostram a porcentagem (ou "MAX" no cap). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,16 +7,27 @@
|
|||||||
|
|
||||||
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)
|
||||||
@@ -33,16 +44,24 @@ void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Sn
|
|||||||
FString::Printf(TEXT("<pct>LVL </><num>%d</>"), Snapshot.BaseLevel)));
|
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 (estilo Default, sem markup de %); as barras + o "%"
|
// server via JobsDatabase). Em cap (ToNext=0) a barra enche e o readout
|
||||||
// ficam pra quando a curva de exp existir no snapshot do servidor.
|
// 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);
|
||||||
|
|||||||
@@ -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