feat(client): AttributeSystem (Fase 1-3) + ZMMOJobs + UI in-game #3
Reference in New Issue
Block a user
Delete Branch "feat/attribute-system-mmo"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implementa AttributeSystem cliente completo (Fase 1-3) + UI in-game completa (HUD HP/SP, Status Window com alocação, toast level up) + novo módulo ZMMOJobs (peer de ZMMOAttributes) com DataAsset-based job registry. Espelha o trabalho do server ZeusServerEngine#9.
Frentes incluídas (6 commits)
7d83dd8Cliente Fase 1 — sub-móduloZMMOAttributes+ HUD HP/SP396223eUI in-game system + PlayerState + Component Registry + HUD compositef585b0dStatus Window — alocação STR/AGI/VIT/INT/DEX/LUK + derivados (ATK/MATK/DEF/MDEF/HIT/FLEE/CRIT/ASPD)5418da1Display "ATK base + bonus" igual RO + ASPD único (não-splittado)dbc2898Toast "LEVEL UP!" no HUD viaS_LEVEL_UPdelegatebacf987Novo módulo ZMMOJobs (peer de ZMMOAttributes) +DA_Job_Novice+ UICharCard bindingZMMOJobs (commit final)
Sub-módulo cliente do JobsSystem server. Pavimenta dados visuais/UI por job (
DisplayNamelocalizado, ícone, anim override, som de level up) sem acoplar aoZMMOAttributes.Arquitetura
Espelho do AttributeSystem do servidor (Game/MMO/Modules/AttributeSystem). Sub-modulo C++ Source/ZMMOAttributes/ (Runtime, LoadingPhase=PreDefault) isolando o cliente do AttributeSystem em pasta propria — pavimentando o caminho para futuros Inventory/Skills/Combat virem como sub-modulos peer. Componentes: - FZMMOAttributesSnapshot (USTRUCT Blueprint, espelha FZeusAttributesPayload do plugin ZeusNetwork) - UZMMOAttributeComponent (UActorComponent ligado ao player): ApplySnapshot / ApplyHpSpUpdate / NotifyLevelUp + 3 delegates dinamicos (OnAttributesChanged / OnHpSpChanged / OnLevelUp) + helpers GetHpRatio / GetSpRatio - UZMMOAttributeNetworkHandler (UWorldSubsystem): ponte UZeusNetworkSubsystem -> componente via lookup por EntityId - UZMMOHudHpSpWidget (UUserWidget base): BindWidget (HpBar, SpBar) + BindWidgetOptional (HpText, SpText, LevelText). NativeConstruct binda nos delegates do componente; NativeDestruct desliga. OnSnapshotApplied / OnHpSpDelta (BlueprintNativeEvent) com impl C++ atualizando progress bars e textos. Integracao no PlayerCharacter: - CreateDefaultSubobject<UZMMOAttributeComponent> no ctor - HudHpSpWidgetClass (TSubclassOf) resolvido via ConstructorHelpers::FClassFinder em /Game/ZMMO/UI/HUD/WBP_HUD_HpSpBar - HandleLocalSpawnReady seed do EntityId no componente + spawn do HUD (CreateWidget + AddToViewport + BindToAttributeComponent) - EndPlay remove widget do parent WBP_HUD_HpSpBar (UMG, criado via MCP): - Overlay root + SizeBox (320x120) + VerticalBox - 5 widgets BindWidget: LevelText, HpBar (vermelho), HpText, SpBar (azul), SpText - Herda de UZMMOHudHpSpWidget Verificacao (smoke test): - PIE login -> server envia S_ATTRIBUTE_SNAPSHOT_FULL - Cliente recebe via OnAttributeSnapshotFull -> handler roteia pra componente do entity -> ApplySnapshot dispara OnAttributesChanged -> widget atualiza ProgressBars + TextBlocks - HUD aparece no canto inferior esquerdo da tela com valores correspondentes ao DB Refs: - Plano: C:/Users/mateu/.claude/plans/temos-uma-lab-input-nested-diffie.md - Server companion commit: feat(attributes): AttributeSystem modular Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Espelho simétrico do front-end pattern (UUIFrontEndFlowSubsystem + DA_FrontEndScreenSet + UUIPrimaryGameLayout_Base) para a UI in-game. Pavimenta caminho pra Inventory, Skills, StatusWindow, EscapeMenu, etc. ## UI in-game system (Source/ZMMO/Game/UI/InGame/) - EZMMOInGameUIState enum (None, Playing, StatusWindow, Inventory, SkillTree, EscapeMenu, Loading) em Data/UI/InGameTypes.h - UUIInGameScreenSet DataAsset: TMap<EZMMOInGameUIState, TSoftClassPtr<...>> - UUIInGameFlowSubsystem (GameInstanceSubsystem) com SetState/ToggleScreen - DA_InGameScreenSet em Content/ZMMO/UI/InGame/ mapeia Playing->WBP_HUD - Layer routing: Playing -> UI.Layer.Game | menus -> GameMenu | loading -> Modal ## AHUD pattern (idiomatic UE5) - AZMMOHUD : AHUD em Source/ZMMO/Game/Modes/ - AZMMOGameMode::HUDClass = AZMMOHUD::StaticClass() - AZMMOHUD::BeginPlay chama UIInGameFlowSubsystem::StartInGame - Pawn não cria mais HUD (separação de responsabilidades) ## PlayerState + Component Registry (Open-Closed) - AZMMOPlayerState : APlayerState em Source/ZMMO/Game/Modes/ - AZMMOGameMode::PlayerStateClass = AZMMOPlayerState::StaticClass() - UPROPERTY Config TArray<TSubclassOf<UActorComponent>> ComponentClasses - DefaultGame.ini: +ComponentClasses=/Script/ZMMOAttributes.ZMMOAttributeComponent - Ctor lê via GConfig (mais robusto que UPROPERTY Config + parsing) e instancia cada componente como CreateDefaultSubobject Por que componentes no PlayerState e não no Pawn: - Sobrevive ao despawn (morte/respawn) - Spectator-friendly - 1:1 com player (Pawn pode trocar: vehicle, mount, possession) - Padrão MMO clássico (rathena, TrinityCore) Adicionar novo módulo (Inventory, Skills, Guild) = 1 linha no DefaultGame.ini, sem editar AZMMOPlayerState.cpp. ## HUD composite - UZMMOHudWidget : UCommonActivatableWidget em ZMMO core (UI/InGame/) - WBP_HUD em Content/ZMMO/UI/HUD/ herda UZMMOHudWidget - HpSpBar (UZMMOHudHpSpWidget — sub-modulo ZMMOAttributes) embedded via BindWidgetOptional. Sub-widgets futuros: PlayerInfo, Minimap, QuickBar, Buffs, Chat, TargetInfo - UZMMOHudHpSpWidget volta a ser UUserWidget puro (sub-widget, não root) - UZMMOHudWidget::NativeOnActivated: - SetVisibility(HitTestInvisible) — mouse passa direto pro Pawn - BindToLocalPlayer: busca AttributeComponent no PC->PlayerState - Subscreve OnAttributesChanged/OnHpSpChanged/OnLevelUp - Propaga snapshots pra sub-widgets via HpSpBar->ApplySnapshot - GetDesiredInputConfig override: ECommonInputMode::Game (sem cursor, movimento livre). Menus override pra GameAndMenu/Menu. ## NetworkHandler refatorado (AttributeComponent agora no PlayerState) - ZMMOAttributeNetworkHandler::FindComponentForEntity: busca via GameState->PlayerArray (O(N_players)), não TActorIterator (O(N_actors)) - ZMMOAttributes.Build.cs += CommonUI, CommonInput ## EnsureRootLayout (fix crítico) - OpenLevel invalida widgets no viewport ("InvalidateAllWidgets") - RootLayout (criado pelo FrontEndFlow no boot) sobrevive como UObject (LocalPlayerSubsystem) mas fica órfão fora do viewport - Push do WBP_HUD no Stack_Game funcionava mas widget pai (RootLayout) estava fora do viewport → invisível - UUIFrontEndFlowSubsystem::EnsureRootLayout (público) recria via UIManagerSubsystem (idempotente) - UUIInGameFlowSubsystem::StartInGame chama EnsureRootLayout antes do push ## PlayerCharacter simplificado - Removido AttributeComponent (vai pro PlayerState via Registry) - Removido HudHpSpWidgetClass + spawn manual de HUD - HandleLocalSpawnReady só faz seed do EntityId via PlayerState - UI lifecycle agora é responsabilidade do AZMMOHUD::BeginPlay ## Verificação (smoke test) PIE: Login -> CharSelect -> Lobby -> EnterWorld ↓ LogZMMO: AZMMOPlayerState ctor: 1 componente(s) no registry LogZMMO: ZMMOPlayerState: componente registrado [0] ZMMOAttributeComponent LogZMMO: FrontEndFlow::EnsureRootLayout: RootLayout recriado LogZMMO: InGameFlow: state None -> Playing LogZMMO: InGameFlow: tela Playing pushed em UI.Layer.Game (widget=WBP_HUD_C_0) LogZMMO: ZMMOHudWidget activated (HpSpBar=WBP_HUD_HpSpBar_C_0) ↓ HUD aparece com Lv 5 / HP 10/200 / SP 5/20 (valores do DB) Regen funciona (HP/SP enchem a cada 6s/8s) Movimento normal (input flui pro Pawn) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>