- ZMMOStatusWindowWidget (UCommonActivatableWidget, modo Menu): grid 2 colunas estilo RO. Esquerda: stats primários com botões + por stat (RequestStatAlloc). Direita: derivados ATK/MATK/DEF/MDEF/HIT/FLEE/CRIT/ASPD vindos do snapshot do server — cliente NUNCA recalcula (anti-cheat foundation). - Botão + envia C_STAT_ALLOC → server valida cost RO (floor((stat-1)/10)+2), aplica + recalcula derivados + SaveCharFull async, manda S_ATTRIBUTE_SNAPSHOT_FULL + reply. UI atualiza em tempo real via OnAttributesChanged. - ZMMOAttributeComponent ganha RequestStatAlloc + NotifyStatAllocReply + delegate OnStatAllocReply para feedback de rejeição. - ZMMOAttributeNetworkHandler: HandleStatAllocReply roteia pro componente do player local (reply não traz EntityId — sempre quem fez o request). - PlayerController: hotkey Alt+A (FInputChord legacy + BindKey, sem precisar de IA asset). ToggleStatusWindow via UUIInGameFlowSubsystem. - WBP_StatusWindow: layout 2 colunas via MCP set_widget_tree (43 widgets) + BgBorder escuro semi-transparente + centralizado no overlay. - DA_InGameScreenSet: StatusWindow → WBP_StatusWindow.
56 lines
1.5 KiB
C++
56 lines
1.5 KiB
C++
#include "ZMMOAttributeComponent.h"
|
|
|
|
#include "Engine/GameInstance.h"
|
|
#include "ZeusNetworkSubsystem.h"
|
|
|
|
UZMMOAttributeComponent::UZMMOAttributeComponent()
|
|
{
|
|
PrimaryComponentTick.bCanEverTick = false;
|
|
}
|
|
|
|
void UZMMOAttributeComponent::ApplySnapshot(const FZMMOAttributesSnapshot& InSnapshot)
|
|
{
|
|
const int32 OldHp = Current.Hp;
|
|
const int32 OldSp = Current.Sp;
|
|
Current = InSnapshot;
|
|
OnAttributesChanged.Broadcast(Current);
|
|
if (OldHp != Current.Hp || OldSp != Current.Sp)
|
|
{
|
|
OnHpSpChanged.Broadcast(Current.Hp, Current.Sp);
|
|
}
|
|
}
|
|
|
|
void UZMMOAttributeComponent::ApplyHpSpUpdate(int32 NewHp, int32 NewSp)
|
|
{
|
|
if (Current.Hp == NewHp && Current.Sp == NewSp)
|
|
{
|
|
return;
|
|
}
|
|
Current.Hp = NewHp;
|
|
Current.Sp = NewSp;
|
|
OnHpSpChanged.Broadcast(Current.Hp, Current.Sp);
|
|
}
|
|
|
|
void UZMMOAttributeComponent::NotifyLevelUp(int32 NewBaseLevel, int32 StatusPointDelta)
|
|
{
|
|
// O snapshot subsequente vai trazer todos os outros campos atualizados —
|
|
// aqui apenas dispara o delegate para efeitos visuais imediatos.
|
|
OnLevelUp.Broadcast(NewBaseLevel, StatusPointDelta);
|
|
}
|
|
|
|
void UZMMOAttributeComponent::NotifyStatAllocReply(bool bAccepted, int32 Reason)
|
|
{
|
|
OnStatAllocReply.Broadcast(bAccepted, Reason);
|
|
}
|
|
|
|
void UZMMOAttributeComponent::RequestStatAlloc(int32 StatId, int32 Amount)
|
|
{
|
|
UWorld* World = GetWorld();
|
|
if (!World) { return; }
|
|
UGameInstance* GI = World->GetGameInstance();
|
|
if (!GI) { return; }
|
|
UZeusNetworkSubsystem* Net = GI->GetSubsystem<UZeusNetworkSubsystem>();
|
|
if (!Net) { return; }
|
|
Net->SendStatAlloc(StatId, Amount);
|
|
}
|