26 Commits

Author SHA1 Message Date
2cd8b3b2bb Merge pull request 'feat/frontend-mainmenu-skeleton' (#1) from feat/frontend-mainmenu-skeleton into main
Reviewed-on: #1
2026-05-19 02:06:46 -03:00
3889680469 feat(ui): painel como o Hyper — texturas reais + Panels editável + fixes
- Realoca as 13 texturas de painel do Hyper p/ /Game/ZMMO/UI/CommonUI/Textures/Panels/ (remove as procedurais)
- DT_UI_Styles.PanelBackground com as 9 entradas fiéis ao Hyper Survival_Gold (DrawAs=Image, Margin 0, tint por chave); PanelOutline vazio como no Hyper
- FUIPanelBrushSet (espelha Struct_UI_Style_Panels): só os 2 mapas
- UUIPanel_Base expõe Panels EditAnywhere (Details como no Hyper), semeado do tema; modo-textura só SetBrush (sem padding/visibility inventados)
- Design-time carrega DT_UI_Styles direto (Designer pinta igual ao runtime)
- Fix: outline ausente usa NoDrawType (antes pintava centro branco com FSlateBrush default)
- Remove membro morto Content/UNamedSlot (Hyper não usa NamedSlot)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 02:03:09 -03:00
bc07c47557 feat(frontend): esqueleto CommonUI de MainMenu (boot→login→lobby)
Estrutura principal de front-end estilo Lyra portada para C++ proprio do
ZMMO (sem CommonGame), seguindo o padrao C++ Abstract -> WBP concreto:

- EZMMOFrontEndState / EZMMOLobbyPage e GameplayTags UI.Layer.* nativos
- UUIActivatableScreen_Base: base de tela (input config, hook de tema,
  voltar) espelhando o padrao de UUIButton_Base
- UUIPrimaryGameLayout_Base: switch principal (4 stacks CommonUI/camada)
- UUIManagerSubsystem (LocalPlayer): dono do root layout, idempotente
- UUIFrontEndFlowSubsystem (GameInstance): maquina de estados + driver
  de rede (Boot->Connecting->Login->ServerSelect->Lobby->EnteringWorld
  ->InWorld); Lobby e o hub logado, paginas internas = EZMMOLobbyPage
- UUIFrontEndScreenSet (DataAsset): mapa estado->tela, forge-ready
- AZMMOFrontEndGameMode + AZMMOFrontEndPlayerController
- GameInstance: bAutoConnectOnStart=false (conexao dirigida pelo fluxo)
- Build.cs: +GameplayTags; ARQUITETURA.md PR-first (s2.1/2.2/3.3/4.8/5)
- Assets: L_FrontEnd (GameMode via World Settings), WBP_PrimaryGameLayout,
  DA_FrontEndScreenSet; Config wiring

WBPs de pagina (Boot/Login/...) virao do Zeus UMG Forge depois (s4.8).
Smoke test PIE OK: root layout no viewport, fluxo Boot->Connecting,
no-op+log para telas nao configuradas, sem crash.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 01:56:16 -03:00
ca781eff83 feat(ui): texturas grunge Aurora Arcana + painel texturizado wired (DT+WBP+teste)
4 UTexture2D procedurais (grunge: base escura + value-noise 2 oitavas + vinheta + manchas + moldura arcana) em Content/ZMMO/UI/CommonUI/Textures/Panels (Square/Horizontal/Vertical + Outline_Gold; sRGB, UI, no-mip). DT_UI_Styles linha Default: Style.Panel.PanelBackground/PanelOutline com FSlateBrush (DrawAs Box/9-slice, Margin 0.22) -> ResourceObject resolvido p/ as texturas (verificado via read_data_table). UI_Panel_Master tree = Background(Border)->Outline(Border) (identico ao Hyper, sem NamedSlot). UI_Test_Panel: PanelA/B/Wide com PanelTexture (Square/Horizontal/Vertical_01). Play L_Test_UI mostra paineis texturizados (modo textura usa FUIStyle do subsystem em runtime).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 01:04:30 -03:00
ca117a559e feat(ui): painel texturizado (padrao Hyper) coexistindo com modo cor
EUIPanelTexture (None, Rectangle_Horizontal_01/02/03, Vertical_01..04, Square_01, Vertical_Footer_01) - espelha o enum Panel do Hyper. FUIStylePanel ganha TMap<EUIPanelTexture,FSlateBrush> PanelBackground + PanelOutline (modelo Struct_UI_Style_Panels), mantendo os tokens de cor. UUIPanel_Base: prop PanelTexture + border Outline; RefreshUIStyle tenta modo TEXTURA (Find brush nos mapas -> SetBrush em Background/Outline) e cai no modo COR (RoundedBox) se nao houver brush. Compila OK. Texturas Aurora Arcana proprias serao geradas (nao importadas do Hyper).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:52:10 -03:00
22fc0fbcc6 test(ui): UI_Test_Panel - SizeBox->UI_Panel_Master direto (paineis preenchem a celula)
Border do painel encolhia (NamedSlot vazio + slot Overlay nao-Fill). Agora cada SizeBox tem o UI_Panel_Master como filho unico -> SizeBox forca 360x200 / 740x160 -> Background preenche a celula e mostra o tema. Botoes (Confirmar/Cancelar Danger/Fechar Ghost) em BtnRow separada. Limite MCP: slot Fill / NamedSlot exigem o Designer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:42:24 -03:00
78f2dd4144 test(ui): salva BP_TestUIHUD religado (BeginPlay->Create UI_Test_Panel->AddToViewport)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:39:02 -03:00
1d363caa96 test(ui): UI_Test_Panel mock de conteudo (SizeBox [ ][ ]/[ ]) + HUD repontado
Layout: Row1 = CellA/CellB (SizeBox 380x240, Overlay = UI_Panel_Master + botoes por cima); CellWide (SizeBox 780x180, painel Secondary + 3 botoes). PanelB=Card, PanelWide=Secondary. BP_TestUIHUD religado (BeginPlay->Create(UI_Test_Panel)->AddToViewport via GetOwningPlayerController). Layout e mock grosseiro (limite do MCP p/ slots) - ajuste fino no Designer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:38:44 -03:00
c6b0be92cc feat(ui): WBP UI_Panel_Master (parent UUIPanel_Base) Background->Content(NamedSlot)
Padrao replicado p/ 2a familia: C++ Abstract (UUIPanel_Base) -> WBP concreto. Arvore: Background(Border) -> Content(NamedSlot) via set_widget_tree; binds casam (Background/Content). Compila 0 erros, parent UUIPanel_Base. Designers injetam conteudo no NamedSlot Content; visual data-driven por FUIStyle.Panel/PanelType.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:29:17 -03:00
01c74c7683 feat(ui): UUIPanel_Base (UCommonUserWidget Abstract) data-driven por FUIStyle.Panel
Mesmo padrao do botao: C++ Abstract -> WBP concreto. PanelType (Primary/Secondary/Tertiary/Card) escolhe Bg/BgRaised/BgSunken/CardSelected; bRoundedBackground (RoundedBox + borda do tema); bUseSmallPadding. Background(UBorder) + Content(UNamedSlot) BindWidgetOptional. RefreshUIStyle resolve FUIStyle.Panel via UZMMOThemeSubsystem, reage a OnThemeChanged; BP_ApplyPanelStyle como hook. Compila OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:26:41 -03:00
f77223cfdb test(ui): setup PIE autocontido p/ UI_Test_Buttons (HUD+PC+GameMode+mapa)
BP_TestUIHUD: BeginPlay -> CreateWidget(UI_Test_Buttons, ctx/owner=GetOwningPlayerController) -> AddToViewport. BP_TestPC: bShowMouseCursor + click/mouseover events (p/ Hover/Pressed). GM_BP_TestGM: HUDClass=BP_TestUIHUD, PlayerControllerClass=BP_TestPC. L_Test_UI (Content/ZMMO/Debug/Maps): basic level com GameMode override = GM_BP_TestGM. Abrir L_Test_UI e dar Play exibe os botoes e permite testar estados. PIE confirmou HUD spawnado.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:22:27 -03:00
1ca546c9e9 test(ui): UI_Test_Buttons (variantes/estados/alinhamento) para smoke test
WBP em /Game/ZMMO/UI/Debug com 6 UI_Button_Master: Primary, Secondary, Danger, Ghost (so borda), Disabled (bIsEnabled=false), AlignLeft+Square (TextAlign=Left, bRoundedBackground=false). Compila 0 erros. Use o botao Play do WBP / PIE p/ exercitar Hover/Pressed/Disabled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:12:32 -03:00
69fe754e34 feat(ui): estados Hover/Pressed/Disabled no botao (ApplyVisualState + NativeOn*)
ApplyVisualState(estado) re-resolve o tema e pinta o Background (RoundedBox/Box) com fill+borda do estado: Normal=BgNormal/BorderNormal, Hovered=BgHover/BorderHover, Pressed=BgPressed/BorderHover, Disabled=BgDisabled/BorderNormal. Overrides do UCommonButtonBase: NativeOnHovered/Unhovered/Pressed/Released(volta p/ Hovered se IsHovered senao Normal)/Enabled/Disabled. RefreshUIStyle agora chama ApplyVisualState(Normal). Compila OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:01:18 -03:00
2da2bc7101 feat(ui): UI_Button_Master tree com widget Background (rename de Bg) + CDO
set_widget_tree renomeia o Border Bg->Background (casa o BindWidgetOptional novo); CDO reaplicado (Style=BSB_Button_Transparent_C, ButtonTextValue, bRoundedBackground=true). Compila 0 erros.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 23:55:07 -03:00
c974efdbc8 feat(ui): Background (rename Bg) com RoundedBox + borda na cor da variante
- Bg -> Background (nome descritivo). - RefreshUIStyle: monta o brush do Background como RoundedBox quando bRoundedBackground (default true): TintColor=BgNormal, OutlineSettings(CornerRadii=Button.CornerRadius, Color=BorderNormal, Width=Button.BorderWidth, RoundingType=FixedRadius). 'So borda com a cor' = variante com BgNormal transparente + BorderNormal na cor (data-driven, como o Hyper). bRoundedBackground=false -> caixa reta. Compila OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 23:48:35 -03:00
98aaac57aa feat(ui): text style CommonTextStyle por variante + reorg assets CommonUI/Style
- BST_Button (UCommonTextStyle, Rajdhani Bold 15) + BSB_Button_Transparent (UCommonButtonStyle) movidos p/ Content/ZMMO/UI/CommonUI/Style/{Text,Button}/ (espelha Hyper). - UI_Button_Master: arvore CommonTextBlock dentro de TextScaleBox (auto-size) via set_widget_tree; Style->BSB_Button_Transparent_C. - DT_UI_Styles linha Default: Style.Button.<variante>.TextStyle -> BST_Button_C (por variante). - ARQUITETURA.md: prefixos BSB_/BST_ (§3.2) + pasta UI/CommonUI/Style + UI/Shared + UI/Fonts (§2.1). Pipeline conferido via read_data_table (4 variantes apontam BST_Button no path novo, cores Aurora Arcana intactas).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 23:39:24 -03:00
2064c37bc3 feat(ui): text style via CommonTextStyle por variante (padrao Hyper) + align + auto-size
FUIStyleButtonVariant.Font (FSlateFontInfo) -> TSubclassOf<UCommonTextStyle> TextStyle (idiomatico CommonUI, como BP_Style_Text_* do Hyper; theme-driven via DT_UI_Styles por variante). ButtonText volta a UCommonTextBlock; RefreshUIStyle: SetStyle(variante.TextStyle) + cor do FUIStyle por cima (FUIStyle manda na cor por tema). Mantidos TextAlign (ETextJustify L/C/R via SetJustification + slot do Overlay) e bAutoSizeText (TextScaleBox ScaleToFit/None) — ortogonais ao CommonTextStyle. ButtonTextValue default 'Button Text' agora no header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 23:12:14 -03:00
abeec244d5 feat(ui): UI_Button_Master estilizado (FUIStyle gold) + style transparente; remove WBP base redundante
- UMG nao permite WBP-com-arvore herdar de WBP-com-arvore: a base abstrata e SO a classe C++ UUIButton_Base. UI_Button_Master reparentado direto p/ /Script/ZMMO.UIButton_Base; WBP UI_Button_Base (redundante) deletado. - UI_Button_Master: arvore propria (SizeBox_Master/Bg/ContentOverlay/ButtonText/Number_Text/Image_Icon/InputActionWidget) via set_widget_tree; ButtonTextValue='Button Text'. - BS_Button_Transparent (novo CommonButtonStyle: brushes NoDraw + padding 0) atribuido ao Style -> remove o fundo branco padrao do UCommonButtonBase; so o Bg (FUIStyle) aparece. - DT_UI_Styles linha Default: Button agora com cores Aurora Arcana (Primary dourado etc.). - ARQUITETURA.md §3.3 corrigido (regra UMG: C++ abstrato -> WBP concreto, variantes sao WBPs irmaos). Compila 0 erros; visual confirmado (dourado + BUTTON TEXT, sem moldura).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:58:10 -03:00
5a8dd796de fix(ui): defaults reais de cor das variantes do botao (Aurora Arcana)
FUIStyleButton ganha construtor que preenche Primary/Secondary/Danger/Ghost com as cores do styles.css (.btn-*). Antes as variantes vinham Transparent/White (placeholder) -> botao saia branco no designer (sem GameInstance usa defaults do struct). Agora ja sai estilizado (Primary=dourado, texto ~#0A0A12) mesmo sem DataTable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:42:22 -03:00
f8f00f9b9d feat(ui): UI_Button_Base tree reconstruida via set_widget_tree (casa BindWidget)
Arvore: SizeBox_Master(SizeBox) -> Bg(Border) -> ContentOverlay(Overlay) -> [ButtonText, Number_Text, Image_Icon (TextBlock/TextBlock/Image), InputActionWidget (CommonActionWidget)]. Todos como variaveis -> ligam nos BindWidgetOptional do UUIButton_Base + InputActionWidget do UCommonButtonBase. UI_Button_Base Abstract + parent UUIButton_Base preservados; UI_Button_Master (concreto) herda; ambos compilam UpToDate 0 erros. Montado pela nova tool set_widget_tree do NwiroIntegrationKit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:32:30 -03:00
4992a56eff fix(ui): ButtonText usa UTextBlock (CommonTextBlock desnecessario; estilo via FUIStyle)
Como o estilo do botao e dirigido pelo FUIStyle (nao pelo CommonTextStyle), trocar UCommonTextBlock->UTextBlock no BindWidgetOptional simplifica e casa com as tools de WBP. Sem perda de comportamento.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:11:31 -03:00
91b080aa68 feat(ui): porte 1:1 do UI_Button_Master (Hyper) para C++ auto-configuravel
UUIButton_Base enriquecido com a logica do UI_Button_Master do Hyper, lida via MCP hyperpro e convertida para C++ (Struct_Style_Button do Hyper substituido pela camada FUIStyle por tema): SetButtonText/SetNumberText/SetIcon/ApplySizeBox/ApplyInputActionStyle/InitializeButton + timeout (delegates OnButtonActivatedByTimeout/OnButtonTimerUpdated). UPROPERTYs editaveis (Button/Text/Number/Icon/Size/InputActionStyle/Timer) auto-aplicados em NativePreConstruct/NativeConstruct. BindWidgetOptional: SizeBox_Master/ButtonText(CommonTextBlock)/Number_Text/Image_Icon/Bg. InputActionWidget acessado por GetWidgetFromName (privado no UCommonButtonBase). Compila+linka OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:58:10 -03:00
4ea5131475 feat(ui): WBP UI_Button_Base (Abstract) + UI_Button_Master
UI_Button_Base: WidgetBlueprint abstrato, parent = UUIButton_Base (C++); arvore RootPanel(Overlay) -> Bg(Border) -> Label(TextBlock), Bg/Label como variaveis (ligam no BindWidgetOptional do C++). UI_Button_Master: child concreto de UI_Button_Base (botao reutilizavel do jogo). Ambos compilam UpToDate, 0 erros. Em /Game/ZMMO/UI/Shared, prefixo UI_ conforme convencao.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:45:40 -03:00
ab74ef8b17 feat(ui): fundacao CommonUI + UUIButton_Base (Abstract)
Habilita CommonUI como base da UI do ZMMO (decisao de arquitetura): modulos CommonUI/CommonInput no Build.cs + include path Game/UI/Widgets; CommonGameViewportClient no DefaultEngine.ini. Adiciona EUIButtonVariant (Primary/Secondary/Danger/Ghost). Cria UUIButton_Base (UCLASS Abstract : UCommonButtonBase): CommonUI cuida de input/foco/click; o C++ resolve os tokens via UZMMOThemeSubsystem::GetActiveUIStyle() e reage a OnThemeChanged; entrega ao WBP por BP_ApplyUIStyle (split contrato C++ / visual Blueprint). CommonInput data/settings deferido p/ a fiacao de input.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:28:45 -03:00
1c06d69174 feat(ui): sistema de UI Style (tokens C++ por tema) + fontes Aurora Arcana
Camada de estilo data-driven do cliente ZMMO, portando o nucleo do projeto de referencia (Hyper) para C++ conforme ARQUITETURA.md (BP Struct proibido):

- Source/ZMMO/Data/UI: UIStyleTypes.h (enums EUI*), UIStyleTokens.h (tokens primitive/semantic/component), UIStyleRow.h (FUIStyle + FUIStyleRow). - ZMMOThemeSubsystem: GetActiveUIStyle() resolve DT_UI_Styles por ThemeId com fallback Default. - Fontes: 8 UFontFace Inline (Cinzel/Rajdhani) em Content/ZMMO/UI/Fonts + DT_UI_Styles preenchido. - ARQUITETURA.md: prefixo de widget UI_, classes base UUI*_Base (UCLASS Abstract) sem prefixo ZMMO. - Config/DefaultGame.ini: UIStyleTable apontando DT_UI_Styles. - Scripts/import_fonts.py (importador idempotente). Inclui tambem o scaffolding do modulo ZMMO ainda nao versionado (Source/ZMMO/Data, Game/UI, Content/ZMMO, uproject, Build.cs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:21:32 -03:00
50471831a2 chore: remove conteudo template da Epic (Variant_*)
Remove os pacotes de exemplo Variant_Combat, Variant_Platforming e Variant_SideScrolling (mais os External Actors/Objects associados) que vieram do template Third Person e nao fazem parte do cliente ZMMO. Ajusta Config/DefaultEditor.ini de acordo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:21:01 -03:00
506 changed files with 4525 additions and 6 deletions

15
.mcp.json Normal file
View File

@@ -0,0 +1,15 @@
{
"mcpServers":
{
"nwiro":
{
"type": "http",
"url": "http://localhost:5353/mcp"
},
"hyperpro":
{
"type": "http",
"url": "http://localhost:5354/mcp"
}
}
}

713
ARQUITETURA.md Normal file
View File

@@ -0,0 +1,713 @@
# Arquitectura do Cliente ZMMO
> Regras de organização do projecto Unreal `ZMMO` (Content + Source) e tutorial
> de como adicionar gameplay novo seguindo o padrão. **Este documento é
> normativo.** Qualquer estrutura nova no projecto tem de respeitar estas
> regras, ou justificar a excepção por escrito.
Última actualização: 2026-05-11.
> **Sumário de mudanças (2026-05-11):** adicionada secção de **temas sazonais
> de UI** (`UI/Themes/`), com tutorial §4.7, regra de "no hard ref a textura
> em widget" em §5 e política de activação em §1.10.
---
## 1. Princípios fundamentais
Estas são as regras que **não negociamos**:
1. **Namespace do projecto.** Todo o conteúdo do jogo vive sob
`Content/ZMMO/`. Nada de assets soltos na raiz `Content/`.
2. **Organizar por feature, não por tipo de asset.** Não criamos pastas
`Meshes/`, `Textures/`, `Materials/` no nível alto. O Content Browser já
filtra por prefixo (`SM_`, `T_`, `M_`...). Pastas existem para refletir
**domínio de gameplay**.
3. **Self-contained por entidade.** Cada Mob, NPC ou Item vive numa pasta
própria que contém **todos os seus assets** (malha, animações, materiais,
texturas, áudio, VFX). Apagar a pasta = remover a entidade do jogo, sem
referências órfãs espalhadas.
4. **Plano (máximo 3 níveis úteis).** Se está a aninhar mais que isso,
provavelmente está a organizar errado. Excepção: dentro de uma entidade
self-contained, sub-pasta `Animations/` é permitida quando o número de
anims ultrapassa 56.
5. **DataTable manda em catálogo, Blueprint manda em comportamento.** Dados
tabulares (stats, drops, preços, descrições) vão em
`Content/ZMMO/Data/**/DT_*.uasset`. Comportamento vai em Blueprints
herdados das bases em `Core/`. Nunca misturar.
6. **Structs e Enums vivem em C++.** Toda `USTRUCT` (row de DataTable
inclusive) e toda `UENUM` é declarada em `Source/ZMMO/Data/`. Blueprint
Structs estão **proibidos** — eles corrompem em refactor e não dão tipos
fortes.
7. **Hierarquia de Entity.** Tudo que vive no mundo herda da mesma raiz:
`BP_Entity_Base` → (`BP_Player_Base` | `BP_NPC_Base` | `BP_Mob_Base`) →
instâncias concretas. Espelha a classe C++ `AZMMOEntity` em
`Source/ZMMO/Game/Entity/`.
8. **Lazy loading via `TSoftObjectPtr`.** Linhas de DataTable e referências
entre features usam soft pointers. Nada de hard ref para BPs de mob/item a
partir da DT mestre — caso contrário carregamos o mundo inteiro ao abrir o
inventário.
9. **`Developers/` e `ExternalContent/` fora do namespace `ZMMO/`.** Não
entram no cook (`Developers/`) e não poluem o nosso namespace
(`ExternalContent/` para Fab/Megascans/Marketplace).
10. **Temas de UI são data-driven, não hard-coded.** Widgets não têm hard
ref para textura/som sazonal — pedem ao `UZMMOThemeSubsystem` via uma
chave declarada em `EZMMOThemeKey` (C++). Veja §1.10 abaixo para a
política de activação.
### 1.10. Política de activação de temas
A UI suporta **temas** (`Default`, `Christmas`, `Halloween`, etc.). A escolha
do tema activo segue esta **ordem de precedência** em runtime:
1. **Override de desenvolvimento** (`DefaultGame.ini`, chave `ActiveTheme=`).
Só lido fora de builds Shipping. Para QA testar Natal em Maio.
2. **Resposta autoritativa do servidor.** Quando o servidor Zeus envia o
opcode `ServerHello` com `ThemeId`, ele vence. É o único caminho válido
em produção.
3. **Calendário local do cliente** (`DT_ThemeCalendar`). Fallback antes do
login (tela de login/character-select aparece antes do servidor falar) e
se o servidor não enviar `ThemeId`.
4. **`DA_Theme_Default`.** Último recurso. Sempre presente, sempre carregado.
**Por que servidor vence:** MMO precisa ligar Halloween fora da data
canónica, fazer evento-surpresa, A/B test de tema sem patch do cliente.
**Por que data local existe:** sem ela, jogador que abre o jogo em 24 de
Dezembro vê tema Default até autenticar — quebra a magia sazonal.
**Por que .ini só fora de Shipping:** evita que um jogador edite o ficheiro
e force um tema que não devia ter acesso (cosméticos pagos, por exemplo).
---
## 2. Estrutura de pastas
### 2.1. `Clients/ZMMO/Content/`
```
Content/
├── ZMMO/ ← namespace do projecto
│ │
│ ├── Core/ ← bases que outros assets herdam
│ │ ├── Entity/
│ │ │ ├── BP_Entity_Base.uasset ← herda AZMMOEntity (C++)
│ │ │ └── BPI_Entity.uasset ← interface comum
│ │ ├── Player/
│ │ │ └── BP_Player_Base.uasset
│ │ ├── NPC/
│ │ │ └── BP_NPC_Base.uasset
│ │ ├── Mob/
│ │ │ ├── BP_Mob_Base.uasset
│ │ │ ├── BT_Mob_Default.uasset ← Behavior Tree base
│ │ │ └── BTT_Mob_*.uasset ← Tasks compartilhadas
│ │ ├── Item/
│ │ │ ├── BP_Item_Base.uasset
│ │ │ └── BPI_Item.uasset
│ │ └── Network/ ← debug do UZMMOWorldSubsystem
│ │
│ ├── Entities/ ← TODAS as instâncias concretas
│ │ ├── Players/
│ │ │ └── Classes/
│ │ │ ├── Warrior/
│ │ │ │ ├── BP_Player_Warrior.uasset
│ │ │ │ ├── SK_Warrior.uasset
│ │ │ │ ├── ABP_Warrior.uasset
│ │ │ │ ├── M_Warrior.uasset
│ │ │ │ ├── T_Warrior_*.uasset
│ │ │ │ └── Animations/
│ │ │ ├── Mage/
│ │ │ └── Archer/
│ │ │
│ │ ├── NPCs/
│ │ │ ├── Vendor_Blacksmith/
│ │ │ │ ├── BP_NPC_Blacksmith.uasset
│ │ │ │ ├── SK_Blacksmith.uasset
│ │ │ │ ├── ABP_Blacksmith.uasset
│ │ │ │ └── ...
│ │ │ └── Questgiver_Elder/
│ │ │
│ │ └── Mobs/
│ │ ├── Beasts/ ← família (organiza, não herda)
│ │ │ ├── Wolf_Gray/ ← pacote completo do mob
│ │ │ │ ├── BP_Mob_Wolf_Gray.uasset
│ │ │ │ ├── SK_Wolf.uasset
│ │ │ │ ├── PHY_Wolf.uasset
│ │ │ │ ├── M_Wolf.uasset
│ │ │ │ ├── MI_Wolf_Gray.uasset
│ │ │ │ ├── T_Wolf_*.uasset
│ │ │ │ ├── Animations/
│ │ │ │ │ ├── ABP_Wolf.uasset
│ │ │ │ │ ├── AS_Wolf_Skel.uasset
│ │ │ │ │ ├── AM_Wolf_AttackBite.uasset
│ │ │ │ │ └── A_Wolf_{Idle,Run,Hit,Death}.uasset
│ │ │ │ ├── Audio/
│ │ │ │ └── VFX/
│ │ │ ├── Bear_Brown/
│ │ │ └── Boar_Wild/
│ │ ├── Undead/
│ │ ├── Humanoids/
│ │ ├── Dragons/
│ │ └── Bosses/
│ │
│ ├── Data/ ← apenas DataTables (.uasset)
│ │ ├── Items/
│ │ │ ├── DT_Items_Master.uasset
│ │ │ ├── DT_Items_Weapons.uasset
│ │ │ ├── DT_Items_Armor.uasset
│ │ │ ├── DT_Items_Consumables.uasset
│ │ │ └── DT_ItemDrops.uasset
│ │ ├── Mobs/
│ │ │ ├── DT_Mobs_Master.uasset
│ │ │ └── DT_MobSpawns.uasset
│ │ ├── Players/
│ │ │ ├── DT_Classes.uasset
│ │ │ └── DT_ExpCurve.uasset
│ │ ├── NPCs/
│ │ │ ├── DT_NPCs.uasset
│ │ │ └── DT_Dialogs.uasset
│ │ ├── Abilities/
│ │ │ ├── DT_Abilities.uasset
│ │ │ └── DT_StatusEffects.uasset
│ │ ├── Quests/
│ │ │ ├── DT_Quests.uasset
│ │ │ └── DT_QuestRewards.uasset
│ │ └── World/
│ │ └── DT_Zones.uasset
│ │
│ ├── Items/ ← assets visuais (modelo/icon dos itens)
│ │ ├── Equipment/
│ │ │ ├── Weapons/
│ │ │ │ ├── Sword_Iron/
│ │ │ │ │ ├── SM_Sword_Iron.uasset
│ │ │ │ │ ├── M_Sword_Iron.uasset
│ │ │ │ │ ├── T_Sword_Iron_*.uasset
│ │ │ │ │ └── T_Icon_Sword_Iron.uasset
│ │ │ │ └── Bow_Hunter/
│ │ │ ├── Armor/
│ │ │ └── Accessories/
│ │ ├── Consumables/
│ │ │ ├── Potion_Health/
│ │ │ └── Potion_Mana/
│ │ ├── Materials/
│ │ └── Quest/
│ │
│ ├── Abilities/ ← VFX/Cues/Montagens (data fica em Data/)
│ │ ├── Combat/ Buffs/ Heals/ Movement/
│ │ └── Shared/
│ │
│ ├── World/
│ │ ├── Maps/ ← L_World_Open, L_City_*, L_Dungeon_*
│ │ ├── Instances/
│ │ ├── Environment/ ← Architecture/ Nature/ Props/
│ │ └── Interactables/ ← baús, portas, warps, recursos
│ │
│ ├── Maps/ ← mapas que NÃO são de mundo
│ │ └── FrontEnd/ ← L_FrontEnd (boot/menu; GameMode via
│ │ World Settings = AZMMOFrontEndGameMode)
│ │
│ ├── UI/ ← HUD, Login, CharacterSelect, Inventory,
│ │ │ Chat, Party, Guild, Trade, Quest, Map,
│ │ │ Shared, Icons
│ │ ├── Shared/ ← WBPs reutilizáveis (UI_Button_Master…)
│ │ ├── FrontEnd/ ← WBP_PrimaryGameLayout, DA_FrontEndScreenSet,
│ │ │ telas refinadas (Boot/Login/… vindas do Forge)
│ │ ├── Fonts/ ← Font_*/FF_* (Cinzel, Rajdhani)
│ │ ├── CommonUI/Style/ ← estilos CommonUI (espelha o Hyper)
│ │ │ ├── Button/ ← BSB_* (UCommonButtonStyle)
│ │ │ └── Text/ ← BST_* (UCommonTextStyle)
│ │ └── Themes/ ← temas sazonais (data-driven, ver §1.10)
│ │ ├── DA_Theme_Default.uasset ← sempre carregado, fallback
│ │ ├── DA_Theme_Christmas.uasset
│ │ ├── DA_Theme_Halloween.uasset
│ │ ├── DT_ThemeCalendar.uasset ← datas → ThemeId (fallback local)
│ │ ├── _Shared/ ← assets reutilizados entre temas
│ │ ├── Default/ ← assets do tema base
│ │ │ ├── HUD/ Login/ Inventory/
│ │ │ ├── Audio/ MS_MainMenu.uasset
│ │ │ └── VFX/
│ │ ├── Christmas/ ← sazonal
│ │ │ ├── HUD/ Login/ Inventory/
│ │ │ ├── Audio/ MS_MainMenu_Christmas.uasset
│ │ │ └── VFX/ NS_Snow.uasset
│ │ └── Halloween/ ... ← mesma estrutura
│ ├── Effects/ ← VFX globais (Niagara)
│ ├── Audio/ ← Music, Ambient, SFX, Voice
│ ├── Input/ ← Enhanced Input
│ ├── Cinematics/ ← Sequencer
│ ├── Movement/ ← Mounts, Transport
│ ├── Localization/ ← StringTables
│ └── Debug/ ← Maps de smoke test
├── Developers/ ← rascunho por dev (não cooka)
│ └── <nick-do-dev>/
├── AutoCreated/ ← saída CRUA do Zeus UMG Forge (HTML→WBP).
│ └── <batch>/ Quarentena: refina-se e MOVE p/ ZMMO/UI/
│ FrontEnd/ antes de produção (não cooka cru)
├── ExternalContent/ ← Fab / Megascans / Marketplace
│ ├── Fab/ Megascans/ Marketplace/
├── Collections/
└── __ExternalActors__/ __ExternalObjects__/ ← World Partition (não mexer)
```
### 2.2. `Clients/ZMMO/Source/ZMMO/`
```
Source/ZMMO/
├── ZMMO.Build.cs
├── ZMMO.h
├── ZMMO.cpp
├── Game/ ← gameplay runtime (já existe)
│ ├── Entity/ ← AZMMOEntity + derivados
│ ├── Controller/ ← AZMMOPlayerController,
│ │ AZMMOFrontEndPlayerController
│ ├── Modes/ ← GameMode + GameInstance,
│ │ AZMMOFrontEndGameMode
│ ├── Network/ ← UZMMOWorldSubsystem
│ └── UI/ ← runtime de UI (não é contrato de dados)
│ ├── ZMMOThemeSubsystem.* ← resolução de tema
│ ├── Widgets/ ← UUIButton_Base, UUIPanel_Base
│ └── FrontEnd/ ← infra de navegação CommonUI:
│ UUIActivatableScreen_Base,
│ UUIPrimaryGameLayout_Base,
│ UUIManagerSubsystem (LocalPlayer),
│ UUIFrontEndFlowSubsystem (GameInstance),
│ UUIFrontEndScreenSet (UDataAsset)
└── Data/ ← contrato de dados (USTRUCT + UENUM)
├── ZMMOData.h ← header agregador (opcional)
├── Items/
│ ├── ItemRow.h ← FItemRow : public FTableRowBase
│ └── ItemTypes.h ← E_ItemType, E_ItemRarity, E_EquipSlot
├── Mobs/
│ ├── MobRow.h ← FMobRow
│ └── MobTypes.h ← E_MobFaction, E_MobBehavior
├── Players/
│ ├── ClassRow.h ← FClassRow
│ └── StatBlock.h ← FStatBlock (HP/MP/Sta/Atk/Def…)
├── NPCs/
│ ├── NPCRow.h
│ └── DialogRow.h
├── Abilities/
│ ├── AbilityRow.h
│ └── StatusEffectRow.h
├── Quests/
│ └── QuestRow.h
├── UI/
│ ├── ThemeKeys.h ← EZMMOThemeKey (HUD_Frame, Login_BG…)
│ ├── ThemeRow.h ← FThemeEntry (Key → SoftAsset)
│ ├── ThemeCalendarRow.h ← FThemeCalendarRow (data → ThemeId)
│ ├── FrontEndTypes.h ← EZMMOFrontEndState, EZMMOLobbyPage
│ └── UILayerTags.h/.cpp ← GameplayTags nativos UI.Layer.*
└── World/
└── ZoneRow.h
```
Regra: **toda DT em `Content/ZMMO/Data/X/`** tem a `Row Structure` definida no
`.h` correspondente em **`Source/ZMMO/Data/X/`**. Espelhamento 1-para-1 nos
nomes das sub-pastas.
O subsystem do tema (`UZMMOThemeSubsystem`) vive em
`Source/ZMMO/Game/UI/` — é gameplay/runtime, não contrato de dados, por isso
não fica em `Data/`.
---
## 3. Convenções de nomenclatura
### 3.1. Pastas
- `PascalCase`, sem espaços, sem acentos.
- Nome no singular para categoria conceitual (`Mob`, `Item`, `Quest`).
- Nome no plural para colecção de instâncias (`Mobs/`, `Items/`, `Quests/`).
- Família de mob/item usa nome temático: `Beasts/`, `Undead/`, `Weapons/`.
- Instância individual usa `Tipo_Variante`: `Wolf_Gray`, `Sword_Iron`,
`Vendor_Blacksmith`.
### 3.2. Assets (prefixo obrigatório)
| Prefixo | Tipo | Exemplo |
|---------|-----------------------------------|-------------------------------|
| `BP_` | Blueprint Class | `BP_Mob_Wolf_Gray` |
| `BPI_` | Blueprint Interface | `BPI_Entity` |
| `UI_` | Widget Blueprint (estilo Hyper) | `UI_Button_Base`, `UI_Inventory_Slot` |
| `ABP_` | Animation Blueprint | `ABP_Wolf` |
| `BT_` | Behavior Tree | `BT_Mob_Default` |
| `BTT_` | Behavior Tree Task | `BTT_Mob_ChasePlayer` |
| `BTS_` | Behavior Tree Service | `BTS_Mob_FindTarget` |
| `BTD_` | Behavior Tree Decorator | `BTD_Mob_CanSeeTarget` |
| `BB_` | Blackboard | `BB_Mob_Default` |
| `SK_` | Skeletal Mesh | `SK_Wolf` |
| `SKEL_` | Skeleton | `SKEL_Wolf` |
| `SM_` | Static Mesh | `SM_Sword_Iron` |
| `PHY_` | Physics Asset | `PHY_Wolf` |
| `M_` | Material | `M_Wolf` |
| `MI_` | Material Instance | `MI_Wolf_Gray` |
| `MF_` | Material Function | `MF_NormalBlend` |
| `T_` | Texture | `T_Wolf_Diffuse` |
| `RT_` | Render Target | `RT_MiniMap` |
| `Font_` | Font (UFont, Composite) | `Font_Cinzel` |
| `FF_` | Font Face (UFontFace, Inline) | `FF_Cinzel_Bold` |
| `BSB_` | Common Button Style (UCommonButtonStyle) | `BSB_Button_Transparent` |
| `BST_` | Common Text Style (UCommonTextStyle) | `BST_Button` |
| `NS_` | Niagara System | `NS_Wolf_Death` |
| `NE_` | Niagara Emitter | `NE_Sparks_Small` |
| `SC_` | Sound Cue | `SC_Wolf_Growl` |
| `SW_` | Sound Wave | `SW_Wolf_Growl_01` |
| `MS_` | MetaSound Source | `MS_AmbientForest` |
| `MSA_` | Mix MetaSound Asset | `MSA_CombatMix` |
| `A_` | Animation Sequence | `A_Wolf_Idle` |
| `AM_` | Animation Montage | `AM_Wolf_AttackBite` |
| `AS_` | Anim State / Skeleton ref | `AS_Wolf_Skel` |
| `IA_` | Input Action | `IA_Move` |
| `IMC_` | Input Mapping Context | `IMC_Default` |
| `DA_` | Data Asset (PrimaryDataAsset) | `DA_Quest_FirstSteps` |
| `DT_` | Data Table | `DT_Items_Master` |
| `CT_` | Curve Table | `CT_DamageFalloff` |
| `C_` | Curve | `C_AttackPower` |
| `L_` | Level / Map | `L_World_Open` |
| `LS_` | Level Sequence | `LS_OpeningCinematic` |
| `GE_` | Gameplay Effect *(se GAS)* | `GE_StatusBleed` |
| `GA_` | Gameplay Ability *(se GAS)* | `GA_Fireball` |
| `GC_` | Gameplay Cue *(se GAS)* | `GC_Hit_Blood` |
### 3.3. C++ (`Source/ZMMO/Data/`)
- Struct: `F<Nome>Row` quando é linha de DataTable. Ex: `FItemRow`, `FMobRow`.
- Struct genérica (não-DT): `F<Nome>`. Ex: `FStatBlock`.
- Enum: `E<Nome>`. Sempre `UENUM(BlueprintType)` e tipado: `enum class EItemType : uint8`.
- Header path espelha a pasta: `Source/ZMMO/Data/Items/ItemRow.h`
`#include "Data/Items/ItemRow.h"`.
**Exceção — classes base de UI (widgets):** a família de UI **não** leva o
prefixo `ZMMO` (ao contrário de `AZMMOEntity`/`UZMMOGameInstance`). Classe C++
base de widget = `UUI<Componente>_Base`, sempre `UCLASS(Abstract)` (não
instanciável direto; só os filhos derivam — padrão `_Abstract` do Hyper).
Ex.: `UUIButton_Base`, `UUIPanel_Base`, `UUIProgressBar_Base`.
**Sub-regra — infra de navegação de front-end:** as classes que orquestram a
navegação CommonUI seguem o mesmo prefixo `UUI` (sem `ZMMO`) por coerência com
a família de UI, **mesmo não sendo widgets**. Assim: o layout raiz é
`UUIPrimaryGameLayout_Base` (Abstract, widget), a base de tela é
`UUIActivatableScreen_Base` (Abstract, widget), e os subsistemas de UI são
`UUIManagerSubsystem` (`ULocalPlayerSubsystem`) e `UUIFrontEndFlowSubsystem`
(`UGameInstanceSubsystem`). Atores de gameplay do front-end (GameMode,
PlayerController) **mantêm** o prefixo `AZMMO` — não são UI, espelham
`AZMMOGameMode`: `AZMMOFrontEndGameMode`, `AZMMOFrontEndPlayerController`.
**Regra do UMG (importante):** um Widget Blueprint **não pode** herdar de outro
Widget Blueprint que tenha árvore de widgets (UMG aborta a compilação: "apenas
um deles deve ter árvore"). Portanto a camada abstrata é **só a classe C++**
`UUI<X>_Base`. O WBP concreto (prefixo `UI_`, ver §3.2) herda **direto da
classe C++**: `UUIButton_Base` (C++ Abstract) → `UI_Button_Master` (WBP, árvore
própria). Variantes por feature são **WBPs irmãos** sobre a mesma classe C++
(`UI_Button_<Feature>` : `UUIButton_Base`), cada um com a própria árvore
(montada via `set_widget_tree`) — nunca encadeando WBPs.
---
## 4. Tutoriais
### 4.1. Adicionar um Mob novo (ex: `Wolf_Gray`)
**Pré-requisito:** já existe `FMobRow` em
`Source/ZMMO/Data/Mobs/MobRow.h` e `DT_Mobs_Master` em
`Content/ZMMO/Data/Mobs/`.
1. Criar a pasta `Content/ZMMO/Entities/Mobs/Beasts/Wolf_Gray/`.
2. Importar **todos** os assets do lobo dentro dela:
- `SK_Wolf`, `SKEL_Wolf`, `PHY_Wolf`.
- `T_Wolf_Diffuse`, `T_Wolf_Normal`, `T_Wolf_ORM`.
- `M_Wolf` e a variante `MI_Wolf_Gray`.
- `Animations/`: `ABP_Wolf`, `AS_Wolf_Skel`, `A_Wolf_*`, `AM_Wolf_*`.
- `Audio/`: `SC_Wolf_Growl`, `SC_Wolf_Footstep`.
- `VFX/`: `NS_Wolf_Death`.
3. Criar `BP_Mob_Wolf_Gray` **herdando** de `Core/Mob/BP_Mob_Base`.
4. Atribuir no BP: `SK_Wolf` no Mesh, `ABP_Wolf` no AnimClass,
`BT_Mob_Default` (ou um BT próprio se necessário) no AIController.
5. Abrir `Content/ZMMO/Data/Mobs/DT_Mobs_Master.uasset`. Adicionar linha
`Wolf_Gray`:
- `BlueprintRef` = `BP_Mob_Wolf_Gray` (via `TSoftObjectPtr` — soft).
- `Stats` = `FStatBlock` com HP/Atk/Def adequados.
- `Faction` = `EMobFaction::Hostile`.
- `DropTableRow` = `WolfDrops` (linha em `DT_ItemDrops`).
6. Se for dropar loot novo, abrir `DT_ItemDrops` e adicionar a linha
`WolfDrops` com array de `FItemRow` ids + chances.
**Regra:** nunca colocar um asset de `Wolf_Gray` fora de
`Entities/Mobs/Beasts/Wolf_Gray/`. Apagar a pasta tem de remover o mob por
inteiro.
### 4.2. Adicionar um Item novo (ex: `Sword_Iron`)
**Pré-requisito:** `FItemRow` em `Source/ZMMO/Data/Items/ItemRow.h`,
`DT_Items_Master` em `Content/ZMMO/Data/Items/`.
1. Criar `Content/ZMMO/Items/Equipment/Weapons/Sword_Iron/`.
2. Importar `SM_Sword_Iron`, texturas `T_Sword_Iron_*`, material
`M_Sword_Iron`, e o ícone `T_Icon_Sword_Iron`.
3. Abrir `DT_Items_Master`. Adicionar linha `Sword_Iron`:
- `Type` = `EItemType::Weapon`.
- `Rarity` = `EItemRarity::Common`.
- `EquipSlot` = `EEquipSlot::MainHand`.
- `WorldMesh` = `SM_Sword_Iron` (soft).
- `Icon` = `T_Icon_Sword_Iron` (soft).
- `DisplayName`, `Description` via `StringTable` em `Localization/`.
**Sem Blueprint por item.** O item é "data only" — quando precisar de
comportamento especial (ex: poção que cura), criar `BP_Item_Potion_Health`
herdando de `Core/Item/BP_Item_Base` e apontar a coluna `BehaviorClass` da
linha para esse BP. A maioria dos itens **não** tem BP próprio.
### 4.3. Adicionar uma Classe de Player (ex: `Warrior`)
1. Criar `Content/ZMMO/Entities/Players/Classes/Warrior/`.
2. Importar `SK_Warrior`, anims, materiais, etc. (mesmo padrão self-contained
do mob).
3. Criar `BP_Player_Warrior` herdando de `Core/Player/BP_Player_Base`.
4. Adicionar linha `Warrior` em `DT_Classes`:
- `BlueprintRef` = `BP_Player_Warrior` (soft).
- `BaseStats` = `FStatBlock`.
- `LevelUpStats` = `FStatBlock` (delta por nível).
- `StartingAbilities` = `TArray<FName>` de ids em `DT_Abilities`.
### 4.4. Adicionar um NPC (ex: `Vendor_Blacksmith`)
1. Criar `Content/ZMMO/Entities/NPCs/Vendor_Blacksmith/` (self-contained).
2. Criar `BP_NPC_Blacksmith` herdando de `Core/NPC/BP_NPC_Base`.
3. Adicionar linha `Vendor_Blacksmith` em `DT_NPCs`:
- `BlueprintRef` = `BP_NPC_Blacksmith` (soft).
- `Role` = `ENPCRole::Vendor`.
- `ShopInventory` = `TArray<FName>` de ids em `DT_Items_Master`.
- `DialogRoot` = id em `DT_Dialogs`.
### 4.5. Adicionar uma Row Struct em C++
Exemplo: nova struct `FCraftRecipeRow` para receitas de crafting.
1. Criar `Source/ZMMO/Data/Crafting/CraftRecipeRow.h`:
```cpp
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "CraftRecipeRow.generated.h"
USTRUCT(BlueprintType)
struct ZMMO_API FCraftRecipeRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FName OutputItem;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
int32 OutputQuantity = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TArray<FName> Ingredients;
};
```
2. Recompilar o módulo `ZMMO`.
3. No editor: `Content/ZMMO/Data/Crafting/``Add → Miscellaneous → Data Table`
→ escolher `CraftRecipeRow` como Row Structure → salvar como
`DT_Crafting_Recipes`.
### 4.6. Conectar uma DataTable a um Blueprint em runtime
```cpp
// Em BP_Mob_Base (ou na sua classe C++ AZMMOMobBase):
//
// UPROPERTY(EditDefaultsOnly, Category="Data")
// TSoftObjectPtr<UDataTable> MobsTable;
//
// UPROPERTY(EditAnywhere, Category="Data")
// FName MobId;
//
// void AZMMOMobBase::BeginPlay()
// {
// Super::BeginPlay();
// if (UDataTable* Table = MobsTable.LoadSynchronous())
// {
// if (FMobRow* Row = Table->FindRow<FMobRow>(MobId, TEXT("Mob init")))
// {
// ApplyStats(Row->Stats);
// Faction = Row->Faction;
// DropTableRowId = Row->DropTableRow;
// }
// }
// }
```
Regra: o `MobId` é setado pelo `UZMMOWorldSubsystem` quando o servidor envia
o opcode de spawn. O cliente nunca instancia mob "por nome" — sempre via id.
### 4.7. Adicionar um tema sazonal (ex: `Christmas`)
**Pré-requisito:** já existem `EZMMOThemeKey` em
`Source/ZMMO/Data/UI/ThemeKeys.h`, `FThemeEntry` em `ThemeRow.h`, e o
`UZMMOThemeSubsystem` em `Source/ZMMO/Game/UI/`.
1. Criar a pasta `Content/ZMMO/UI/Themes/Christmas/` com sub-pastas que
espelham as features de UI a substituir: `HUD/`, `Login/`, `Inventory/`,
`Audio/`, `VFX/`. Não precisa criar sub-pastas para features que o tema
**não** altera.
2. Importar os assets variantes lá dentro. Manter os **mesmos nomes** que os
equivalentes em `Themes/Default/` ajuda a comparar:
- `Themes/Default/HUD/T_HUD_Frame.uasset`
`Themes/Christmas/HUD/T_HUD_Frame.uasset`.
3. Criar `DA_Theme_Christmas.uasset` em `Content/ZMMO/UI/Themes/` como
`PrimaryDataAsset` herdando da classe `UZMMOThemeDataAsset` (a classe
vive em `Source/ZMMO/Game/UI/`).
4. Preencher o `TMap<EZMMOThemeKey, FThemeEntry>` do data asset **apenas com
as chaves que o tema sobrescreve**. As que ficam vazias caem
automaticamente para `DA_Theme_Default`.
5. Adicionar linha em `DT_ThemeCalendar`:
- `ThemeId` = `Christmas`.
- `StartDate` = `12-15`.
- `EndDate` = `01-05`.
- `Priority` = `10` (caso duas datas se sobreponham).
6. No servidor Zeus, quando quiser activar o tema (autoritativo), enviar o
opcode `ServerHello` com `ThemeId = "Christmas"`. Em ausência disso, o
cliente usa o calendário do passo 5.
**Adicionar uma chave nova de tema** (ex: tela de loading sazonal):
1. Abrir `Source/ZMMO/Data/UI/ThemeKeys.h` e adicionar o valor ao enum:
```cpp
UENUM(BlueprintType)
enum class EZMMOThemeKey : uint8
{
HUD_Frame,
Login_Background,
Login_Logo,
Inventory_SlotEmpty,
LoadingScreen, // <-- nova chave
MainMenu_Music,
};
```
2. Recompilar o módulo `ZMMO`.
3. Abrir `DA_Theme_Default` no editor e preencher a nova chave **obrigatoriamente**
(Default tem de ter todas).
4. Preencher nos temas sazonais apenas se quiser substituir.
**Regra de ouro do tema:** widget consome via subsystem, nunca por hard ref.
```cpp
// Em vez de:
// UPROPERTY(EditAnywhere) TObjectPtr<UTexture2D> HudFrameTex;
//
// Faz:
// const UZMMOThemeSubsystem* Theme = GetGameInstance()->GetSubsystem<UZMMOThemeSubsystem>();
// SetBrushFromSoftTexture(Theme->GetTexture(EZMMOThemeKey::HUD_Frame));
```
O subsystem aplica fallback internamente: pergunta ao tema activo; se a
chave não estiver preenchida, devolve a do `Default`.
### 4.8. Adicionar uma tela de front-end (ex: `Login`)
**Pré-requisito:** já existem `UUIActivatableScreen_Base` e
`UUIFrontEndFlowSubsystem` em `Source/ZMMO/Game/UI/FrontEnd/`, o
`WBP_PrimaryGameLayout` e o `DA_FrontEndScreenSet` em
`Content/ZMMO/UI/FrontEnd/`.
Fluxo geral: **Boot → Connecting → Login → ServerSelect → Lobby → EnteringWorld
→ InWorld**. O **Lobby** é o hub principal logado; suas páginas internas
(CharacterSelect, CharacterCreate, Shop, Settings…) são `EZMMOLobbyPage`,
navegadas por um stack CommonUI **dentro** da tela do Lobby — não são estados
de topo do fluxo.
1. Prototipar a tela em HTML/CSS em `Tools/Templates/MMO_Widget/` (ou usar os
templates já existentes).
2. Rodar o Zeus UMG Forge (HTML→UMG). Saída crua: `Content/AutoCreated/<batch>/`.
3. Abrir o `WBP_*` gerado e **reparent** a classe pai para
`UUIActivatableScreen_Base` (a base é `UCommonActivatableWidget`; o WBP tem
árvore própria — respeita §3.3, nunca encadeia WBP→WBP).
4. **Reconectar tema:** o Forge gera hard ref de textura (proibido §5).
Substituir por consumo via `UZMMOThemeSubsystem` por `EZMMOThemeKey` no
override de `RefreshUIStyle`; remontar botões/painéis com os widgets
compartilhados (`UI_Button_Master`, `UI_Panel_Master`).
5. **Mover** o asset refinado de `Content/AutoCreated/…` para
`Content/ZMMO/UI/FrontEnd/` (o cru não cooka).
6. Registrar no `DA_FrontEndScreenSet`: `StateScreens[EZMMOFrontEndState::Login]`
= soft class do WBP refinado (páginas do Lobby vão no map de
`EZMMOLobbyPage` da tela de Lobby). Sem registro, o flow faz no-op + log.
**Regra:** uma tela nunca segura hard ref a asset de tema (textura/som/VFX) —
sempre via `UZMMOThemeSubsystem` por `EZMMOThemeKey` (igual §4.7 e §5).
---
## 5. O que **NÃO** fazer
- **Não** criar pastas `Meshes/`, `Textures/`, `Materials/` no nível alto.
- **Não** criar `Blueprint Struct` no editor. Toda struct é C++.
- **Não** referenciar BPs de mob/item com `TObjectPtr<>` (hard ref) a partir
de DataTables ou Subsystems globais — usar `TSoftObjectPtr<>`.
- **Não** misturar assets de uma entidade com assets de outra. Cada
Wolf_Gray, Sword_Iron, etc. é uma pasta isolada.
- **Não** colocar nada na raiz `Content/`. Tudo é `Content/ZMMO/...` ou
`Content/{Developers,AutoCreated,ExternalContent}/...`. `AutoCreated/` é
quarentena do Zeus UMG Forge: refina-se e **move** para `ZMMO/UI/FrontEnd/`
antes de produção; o cru não cooka.
- **Não** importar conteúdo do Fab/Megascans directo para dentro de `ZMMO/`.
Vai sempre para `ExternalContent/` e, se quiser usar, **referencia** dali.
- **Não** colocar dados tabulares em Blueprint (lista hardcoded de itens,
array de stats no ABP). Move para DataTable.
- **Não** duplicar `FStatBlock` em C++ se já existe — importar de
`Source/ZMMO/Data/Players/StatBlock.h`.
- **Não** colocar hard ref de textura/som de tema dentro de um Widget
(`TObjectPtr<UTexture2D> ChristmasFrame` é proibido). Widgets pedem ao
`UZMMOThemeSubsystem` via `EZMMOThemeKey`. Hard ref a asset de tema
bloqueia a troca em runtime e quebra a política de fallback. Vale também
para **telas de front-end** (Boot/Login/ServerSelect/Lobby/…): a saída crua
do Forge traz hard ref — tem de ser reconectada ao subsystem antes do merge
(ver §4.8).
- **Não** criar chave de tema "ad-hoc" como `FName("HUD.Frame")`. Toda chave
é entrada do enum C++ `EZMMOThemeKey`. String literal é proibida — o
compilador tem de quebrar quando alguém esquecer de adicionar a chave.
- **Não** preencher um tema sazonal com **todas** as chaves só porque o
Default preenche. Tema sazonal só lista o que **substitui**; o resto cai
no Default automaticamente.
---
## 6. Excepções permitidas
- Dentro de uma entidade self-contained, sub-pasta `Animations/` é OK quando
passa de 56 anims. O mesmo vale para `Audio/` e `VFX/` próprios da
entidade.
- `Items/.../Equipment/Weapons/Sword_Iron/` mantém o ícone `T_Icon_*` junto
do mesh — é a única excepção em que textura e mesh ficam na mesma pasta
raiz da entidade (porque o ícone é parte do item, não um asset solto).
- Skeleton compartilhado entre variantes (ex: `Wolf_Gray`, `Wolf_Black`)
pode viver em `Entities/Mobs/Beasts/_Shared/Wolf/` se as variantes
reutilizarem o mesmo `SK_` e `Animations/`. Pasta começa com `_` para
ordenar primeiro no Content Browser.
---
## 7. Referências externas
- [Allar UE5 Style Guide](https://github.com/Allar/ue5-style-guide) — base
das nossas convenções de nomenclatura e estrutura.
- [Epic Unreal Engine Directory Structure](https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-directory-structure).
- [Lyra Project Structure](https://github.com/iliags/LyraGameVault/blob/main/Lyra%20Project%20Structure.md)
— modelo Epic para projecto multiplayer escalável.
- [Hyperdense UE5 folder structure best practices](https://medium.com/@sarah.hyperdense/ue5-project-folder-structure-and-organization-best-practices-b9e487c330a3).
- [Epic Forum Using DataTables, Structs and DataAssets for Inventory](https://forums.unrealengine.com/t/using-data-tables-structs-and-data-assets-for-an-inventory/2381408).
- [Epic Forum Item system: how to structure/store data](https://forums.unrealengine.com/t/item-system-how-to-structure-store-data/2170364).
---
## 8. Como mudar este documento
Este `.md` é a fonte de verdade da arquitectura do cliente. Mudanças
estruturais (nova pasta no nível alto, mudança de convenção de nome, novo
tipo de asset) **precisam de PR alterando este ficheiro primeiro**. Sem PR
neste documento, não se mexe na árvore real.

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/ThirdPerson/Lvl_ThirdPerson.Lvl_ThirdPerson
EditorStartupMap=/Game/ThirdPerson/Lvl_ThirdPerson.Lvl_ThirdPerson
GameDefaultMap=/Game/ZMMO/Maps/FrontEnd/L_FrontEnd.L_FrontEnd
EditorStartupMap=/Game/ZMMO/Maps/FrontEnd/L_FrontEnd.L_FrontEnd
; GameMode/PlayerController/PlayerCharacter agora moram em C++ (Game/Modes/Entity/Controller).
; O motor pode spawnar AZMMOGameMode directamente; um BP filho continua opcional.
GlobalDefaultGameMode=/Script/ZMMO.ZMMOGameMode
@@ -75,6 +75,8 @@ DefaultGraphicsPerformance=Maximum
AppliedDefaultGraphicsPerformance=Maximum
[/Script/Engine.Engine]
; CommonUI: viewport client que roteia input (teclado/gamepad) e foco para a UI.
GameViewportClientClassName=/Script/CommonUI.CommonGameViewportClient
+ActiveGameNameRedirects=(OldGameName="TP_ThirdPerson",NewGameName="/Script/ZMMO")
+ActiveGameNameRedirects=(OldGameName="/Script/TP_ThirdPerson",NewGameName="/Script/ZMMO")
; Redirects do template antigo para a nova arquitectura (Game/Modes/Entity/Controller).

View File

@@ -1,3 +1,31 @@
[/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

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

Binary file not shown.

View File

View File

View File

Binary file not shown.

View File

View File

View File

View File

Some files were not shown because too many files have changed in this diff Show More