Files
ZMMO/Config/DefaultGame.ini
Mateus Rodrigues 396223e2a8 feat(ui-ingame): UI in-game system + PlayerState + Component Registry + HUD composite
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>
2026-05-23 05:27:41 -03:00

60 lines
3.2 KiB
INI

[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=FC3E256F43B2AFD43009F4949B0814BE
ProjectName=Third Person Game Template
; -----------------------------------------------------------------------------
; ZMMO Theme subsystem (see Source/ZMMO/Game/UI/ZMMOThemeSubsystem.h and
; ARQUITETURA.md §1.10 / §4.7).
;
; - DefaultThemeAsset is the fallback theme (must define every EZMMOThemeKey).
; - ThemeRegistry maps ThemeId -> seasonal DA_Theme_* asset.
; - CalendarTable points to DT_ThemeCalendar (FThemeCalendarRow rows).
; - UIStyleTable points to DT_UI_Styles (FUIStyleRow rows): tokens de estilo
; (cores/fontes/dimensões) keyed por ThemeId; linha "Default" é o fallback.
; - DevThemeOverride forces a theme in non-Shipping builds only. Keep commented
; in production.
;
; Paths use the /Game prefix (cooked Content namespace). Uncomment after the
; assets are actually created in the editor.
; -----------------------------------------------------------------------------
[/Script/ZMMO.ZMMOThemeSubsystem]
;DefaultThemeAsset=/Game/ZMMO/UI/Themes/DA_Theme_Default.DA_Theme_Default
;+ThemeRegistry=(("Christmas", "/Game/ZMMO/UI/Themes/DA_Theme_Christmas.DA_Theme_Christmas"))
;+ThemeRegistry=(("Halloween", "/Game/ZMMO/UI/Themes/DA_Theme_Halloween.DA_Theme_Halloween"))
;CalendarTable=/Game/ZMMO/UI/Themes/DT_ThemeCalendar.DT_ThemeCalendar
UIStyleTable=/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles
;DevThemeOverride=Christmas
[/Script/ZMMO.UIFrontEndFlowSubsystem]
; Mapa estado->tela. O DA já existe (RootLayoutClass = WBP_PrimaryGameLayout);
; StateScreens fica vazio até os WBPs de página virem do Zeus UMG Forge (§4.8).
ScreenSetAsset=/Game/ZMMO/UI/FrontEnd/DA_FrontEndScreenSet.DA_FrontEndScreenSet
; Fase 4 — char spawn DB-driven. DT_Maps espelha o `maps_config.json` do
; server (Server/ZeusServerEngine/Config/DataTables/maps_config.json) — o
; cliente resolve `mapId -> ClientLevel/spawns` via FZMMOMapDef rows.
MapsTableAsset=/Game/ZMMO/Data/World/DT_Maps.DT_Maps
; -----------------------------------------------------------------------------
; UI in-game (PR 19+). Espelho do front-end pattern:
; - ScreenSetAsset mapeia EZMMOInGameUIState -> WBP (Playing -> WBP_HUD,
; StatusWindow -> WBP_StatusWindow, etc.)
; - Subsystem orquestra: AZMMOHUD::BeginPlay chama StartInGame que vai pra
; Playing.
; Asset criado via MCP em /Game/ZMMO/UI/InGame/DA_InGameScreenSet.
; -----------------------------------------------------------------------------
[/Script/ZMMO.UIInGameFlowSubsystem]
ScreenSetAsset=/Game/ZMMO/UI/InGame/DA_InGameScreenSet.DA_InGameScreenSet
; -----------------------------------------------------------------------------
; PlayerState Component Registry (PR 19+). Cada módulo MMO registra seus
; UActorComponent aqui. O AZMMOPlayerState lê esta lista no construtor e
; instancia cada classe como subobject — pattern Open-Closed: adicionar
; Inventory/Skills/Guild = mais uma linha aqui, sem editar AZMMOPlayerState.
;
; Convenção: usa o path /Script/<Module>.<ClassName> (sem o "U" do prefixo
; C++; UClass resolve pelo nome curto).
; -----------------------------------------------------------------------------
[/Script/ZMMO.ZMMOPlayerState]
+ComponentClasses=/Script/ZMMOAttributes.ZMMOAttributeComponent