From ede49c177776a79b12613ee5a7f125e4d114dce5 Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Date: Thu, 28 May 2026 03:58:33 -0300 Subject: [PATCH] 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) --- .../UI/InGame/ZMMOHudPlayerVitalsWidget.cpp | 41 ++++++++++++++----- .../Private/ZMMOAttributeNetworkHandler.cpp | 6 ++- .../Public/ZMMOAttributeTypes.h | 5 +++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp b/Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp index 872f4ca..f945626 100644 --- a/Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp +++ b/Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp @@ -7,16 +7,27 @@ 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) { return Max > 0 ? FMath::Clamp(static_cast(Current) / static_cast(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(static_cast(Cur) / static_cast(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(Cur) / static_cast(ToNext) * 100.0; + return FText::FromString(FString::Printf(TEXT("%.2f%%"), Pct)); + } } void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Snapshot) @@ -33,16 +44,24 @@ void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Sn FString::Printf(TEXT("LVL %d"), Snapshot.BaseLevel))); } - // BASE / JOB EXP — sem "exp-to-next" no snapshot. Readout mostra valor - // absoluto acumulado (estilo Default, sem markup de %); as barras + o "%" - // ficam pra quando a curva de exp existir no snapshot do servidor. + // BASE / JOB EXP — barras em % (exp atual / exp-to-next, resolvido pelo + // 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) { - ExpReadout->SetText(FormatNumber(Snapshot.BaseExp)); + ExpReadout->SetText(ExpReadoutText(Snapshot.BaseExp, Snapshot.BaseExpToNext)); } if (JobReadout) { - JobReadout->SetText(FormatNumber(Snapshot.JobExp)); + JobReadout->SetText(ExpReadoutText(Snapshot.JobExp, Snapshot.JobExpToNext)); } OnSnapshotApplied(Snapshot); diff --git a/Source/ZMMOAttributes/Private/ZMMOAttributeNetworkHandler.cpp b/Source/ZMMOAttributes/Private/ZMMOAttributeNetworkHandler.cpp index b9c702b..f272c73 100644 --- a/Source/ZMMOAttributes/Private/ZMMOAttributeNetworkHandler.cpp +++ b/Source/ZMMOAttributes/Private/ZMMOAttributeNetworkHandler.cpp @@ -19,9 +19,11 @@ namespace S.EntityId = P.EntityId; S.ClassId = P.ClassId; S.BaseLevel = P.BaseLevel; - S.BaseExp = P.BaseExp; + S.BaseExp = P.BaseExp; + S.BaseExpToNext = P.BaseExpToNext; S.JobLevel = P.JobLevel; - S.JobExp = P.JobExp; + S.JobExp = P.JobExp; + S.JobExpToNext = P.JobExpToNext; S.Str = P.Str; S.Agi = P.Agi; S.Vit = P.Vit; diff --git a/Source/ZMMOAttributes/Public/ZMMOAttributeTypes.h b/Source/ZMMOAttributes/Public/ZMMOAttributeTypes.h index aca138a..846a397 100644 --- a/Source/ZMMOAttributes/Public/ZMMOAttributeTypes.h +++ b/Source/ZMMOAttributes/Public/ZMMOAttributeTypes.h @@ -26,8 +26,13 @@ struct ZMMOATTRIBUTES_API FZMMOAttributesSnapshot // === Progressao === UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 BaseLevel = 1; 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") 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) === UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Str = 1;