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>
This commit is contained in:
15
.mcp.json
Normal file
15
.mcp.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"mcpServers":
|
||||||
|
{
|
||||||
|
"nwiro":
|
||||||
|
{
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:5353/mcp"
|
||||||
|
},
|
||||||
|
"hyperpro":
|
||||||
|
{
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:5354/mcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
630
ARQUITETURA.md
Normal file
630
ARQUITETURA.md
Normal file
@@ -0,0 +1,630 @@
|
|||||||
|
# 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 5–6.
|
||||||
|
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
|
||||||
|
│ │
|
||||||
|
│ ├── UI/ ← HUD, Login, CharacterSelect, Inventory,
|
||||||
|
│ │ │ Chat, Party, Guild, Trade, Quest, Map,
|
||||||
|
│ │ │ Shared, Icons
|
||||||
|
│ │ └── 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>/
|
||||||
|
├── 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
|
||||||
|
│ ├── Modes/ ← GameMode + GameInstance
|
||||||
|
│ └── Network/ ← UZMMOWorldSubsystem
|
||||||
|
│
|
||||||
|
└── 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)
|
||||||
|
└── 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` |
|
||||||
|
| `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`. O Widget
|
||||||
|
Blueprint que herda usa prefixo de asset `UI_` (ver §3.2): `UI_Button_Base`
|
||||||
|
(abstrato) → `UI_Button_Master` → `UI_Button_<Feature>`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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,ExternalContent}/...`.
|
||||||
|
- **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.
|
||||||
|
- **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 5–6 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.
|
||||||
@@ -1,3 +1,26 @@
|
|||||||
[/Script/EngineSettings.GeneralProjectSettings]
|
[/Script/EngineSettings.GeneralProjectSettings]
|
||||||
ProjectID=FC3E256F43B2AFD43009F4949B0814BE
|
ProjectID=FC3E256F43B2AFD43009F4949B0814BE
|
||||||
ProjectName=Third Person Game Template
|
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
|
||||||
|
|||||||
0
Content/ZMMO/Abilities/Buffs/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Buffs/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Combat/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Combat/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Heals/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Heals/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Movement/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Movement/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Shared/.gitkeep
Normal file
0
Content/ZMMO/Abilities/Shared/.gitkeep
Normal file
0
Content/ZMMO/Audio/Ambient/.gitkeep
Normal file
0
Content/ZMMO/Audio/Ambient/.gitkeep
Normal file
0
Content/ZMMO/Audio/Music/.gitkeep
Normal file
0
Content/ZMMO/Audio/Music/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/Combat/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/Combat/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/Footsteps/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/Footsteps/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/UI/.gitkeep
Normal file
0
Content/ZMMO/Audio/SFX/UI/.gitkeep
Normal file
0
Content/ZMMO/Audio/Voice/.gitkeep
Normal file
0
Content/ZMMO/Audio/Voice/.gitkeep
Normal file
0
Content/ZMMO/Cinematics/.gitkeep
Normal file
0
Content/ZMMO/Cinematics/.gitkeep
Normal file
0
Content/ZMMO/Core/Entity/.gitkeep
Normal file
0
Content/ZMMO/Core/Entity/.gitkeep
Normal file
0
Content/ZMMO/Core/Item/.gitkeep
Normal file
0
Content/ZMMO/Core/Item/.gitkeep
Normal file
0
Content/ZMMO/Core/Mob/.gitkeep
Normal file
0
Content/ZMMO/Core/Mob/.gitkeep
Normal file
0
Content/ZMMO/Core/NPC/.gitkeep
Normal file
0
Content/ZMMO/Core/NPC/.gitkeep
Normal file
0
Content/ZMMO/Core/Network/.gitkeep
Normal file
0
Content/ZMMO/Core/Network/.gitkeep
Normal file
0
Content/ZMMO/Core/Player/.gitkeep
Normal file
0
Content/ZMMO/Core/Player/.gitkeep
Normal file
0
Content/ZMMO/Data/Abilities/.gitkeep
Normal file
0
Content/ZMMO/Data/Abilities/.gitkeep
Normal file
0
Content/ZMMO/Data/Items/.gitkeep
Normal file
0
Content/ZMMO/Data/Items/.gitkeep
Normal file
0
Content/ZMMO/Data/Mobs/.gitkeep
Normal file
0
Content/ZMMO/Data/Mobs/.gitkeep
Normal file
0
Content/ZMMO/Data/NPCs/.gitkeep
Normal file
0
Content/ZMMO/Data/NPCs/.gitkeep
Normal file
0
Content/ZMMO/Data/Players/.gitkeep
Normal file
0
Content/ZMMO/Data/Players/.gitkeep
Normal file
0
Content/ZMMO/Data/Quests/.gitkeep
Normal file
0
Content/ZMMO/Data/Quests/.gitkeep
Normal file
BIN
Content/ZMMO/Data/UI/DT_UI_Styles.uasset
Normal file
BIN
Content/ZMMO/Data/UI/DT_UI_Styles.uasset
Normal file
Binary file not shown.
0
Content/ZMMO/Data/World/.gitkeep
Normal file
0
Content/ZMMO/Data/World/.gitkeep
Normal file
0
Content/ZMMO/Debug/BP/.gitkeep
Normal file
0
Content/ZMMO/Debug/BP/.gitkeep
Normal file
0
Content/ZMMO/Debug/Maps/.gitkeep
Normal file
0
Content/ZMMO/Debug/Maps/.gitkeep
Normal file
0
Content/ZMMO/Debug/Materials/.gitkeep
Normal file
0
Content/ZMMO/Debug/Materials/.gitkeep
Normal file
0
Content/ZMMO/Effects/Abilities/.gitkeep
Normal file
0
Content/ZMMO/Effects/Abilities/.gitkeep
Normal file
0
Content/ZMMO/Effects/Environment/.gitkeep
Normal file
0
Content/ZMMO/Effects/Environment/.gitkeep
Normal file
0
Content/ZMMO/Effects/Shared/.gitkeep
Normal file
0
Content/ZMMO/Effects/Shared/.gitkeep
Normal file
0
Content/ZMMO/Effects/UI/.gitkeep
Normal file
0
Content/ZMMO/Effects/UI/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Beasts/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Beasts/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Bosses/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Bosses/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Dragons/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Dragons/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Humanoids/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Humanoids/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Undead/.gitkeep
Normal file
0
Content/ZMMO/Entities/Mobs/Undead/.gitkeep
Normal file
0
Content/ZMMO/Entities/NPCs/.gitkeep
Normal file
0
Content/ZMMO/Entities/NPCs/.gitkeep
Normal file
0
Content/ZMMO/Input/Actions/.gitkeep
Normal file
0
Content/ZMMO/Input/Actions/.gitkeep
Normal file
0
Content/ZMMO/Input/Mappings/.gitkeep
Normal file
0
Content/ZMMO/Input/Mappings/.gitkeep
Normal file
0
Content/ZMMO/Input/Modifiers/.gitkeep
Normal file
0
Content/ZMMO/Input/Modifiers/.gitkeep
Normal file
0
Content/ZMMO/Items/Consumables/.gitkeep
Normal file
0
Content/ZMMO/Items/Consumables/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Accessories/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Accessories/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Armor/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Armor/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Weapons/.gitkeep
Normal file
0
Content/ZMMO/Items/Equipment/Weapons/.gitkeep
Normal file
0
Content/ZMMO/Items/Materials/.gitkeep
Normal file
0
Content/ZMMO/Items/Materials/.gitkeep
Normal file
0
Content/ZMMO/Items/Quest/.gitkeep
Normal file
0
Content/ZMMO/Items/Quest/.gitkeep
Normal file
0
Content/ZMMO/Localization/.gitkeep
Normal file
0
Content/ZMMO/Localization/.gitkeep
Normal file
0
Content/ZMMO/Movement/Mounts/.gitkeep
Normal file
0
Content/ZMMO/Movement/Mounts/.gitkeep
Normal file
0
Content/ZMMO/Movement/Transport/.gitkeep
Normal file
0
Content/ZMMO/Movement/Transport/.gitkeep
Normal file
0
Content/ZMMO/UI/CharacterSelect/.gitkeep
Normal file
0
Content/ZMMO/UI/CharacterSelect/.gitkeep
Normal file
0
Content/ZMMO/UI/Chat/.gitkeep
Normal file
0
Content/ZMMO/UI/Chat/.gitkeep
Normal file
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_Bold.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_Bold.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_ExtraBold.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_ExtraBold.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_Regular.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_Regular.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_SemiBold.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Cinzel/FF_Cinzel_SemiBold.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Bold.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Bold.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Medium.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Medium.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Regular.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_Regular.uasset
Normal file
Binary file not shown.
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_SemiBold.uasset
Normal file
BIN
Content/ZMMO/UI/Fonts/Rajdhani/FF_Rajdhani_SemiBold.uasset
Normal file
Binary file not shown.
0
Content/ZMMO/UI/Guild/.gitkeep
Normal file
0
Content/ZMMO/UI/Guild/.gitkeep
Normal file
0
Content/ZMMO/UI/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Icons/.gitkeep
Normal file
0
Content/ZMMO/UI/Icons/.gitkeep
Normal file
0
Content/ZMMO/UI/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Map/.gitkeep
Normal file
0
Content/ZMMO/UI/Map/.gitkeep
Normal file
0
Content/ZMMO/UI/Party/.gitkeep
Normal file
0
Content/ZMMO/UI/Party/.gitkeep
Normal file
0
Content/ZMMO/UI/Quest/.gitkeep
Normal file
0
Content/ZMMO/UI/Quest/.gitkeep
Normal file
0
Content/ZMMO/UI/Shared/.gitkeep
Normal file
0
Content/ZMMO/UI/Shared/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Christmas/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Default/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Audio/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/HUD/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Inventory/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/Login/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/Halloween/VFX/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/_Shared/.gitkeep
Normal file
0
Content/ZMMO/UI/Themes/_Shared/.gitkeep
Normal file
0
Content/ZMMO/UI/Trade/.gitkeep
Normal file
0
Content/ZMMO/UI/Trade/.gitkeep
Normal file
0
Content/ZMMO/World/Environment/Nature/.gitkeep
Normal file
0
Content/ZMMO/World/Environment/Nature/.gitkeep
Normal file
0
Content/ZMMO/World/Environment/Props/.gitkeep
Normal file
0
Content/ZMMO/World/Environment/Props/.gitkeep
Normal file
0
Content/ZMMO/World/Instances/.gitkeep
Normal file
0
Content/ZMMO/World/Instances/.gitkeep
Normal file
0
Content/ZMMO/World/Interactables/.gitkeep
Normal file
0
Content/ZMMO/World/Interactables/.gitkeep
Normal file
0
Content/ZMMO/World/Maps/.gitkeep
Normal file
0
Content/ZMMO/World/Maps/.gitkeep
Normal file
90
Scripts/import_fonts.py
Normal file
90
Scripts/import_fonts.py
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
"""
|
||||||
|
import_fonts.py — Importa as fontes Aurora Arcana para o cliente ZMMO.
|
||||||
|
|
||||||
|
Cria (UFontFace, loading policy = Inline; .ttf embutido no .uasset):
|
||||||
|
Content/ZMMO/UI/Fonts/Cinzel/ FF_Cinzel_Regular | _SemiBold | _Bold | _ExtraBold
|
||||||
|
Content/ZMMO/UI/Fonts/Rajdhani/ FF_Rajdhani_Regular | _Medium | _SemiBold | _Bold
|
||||||
|
|
||||||
|
Source dos .ttf: Tools/Templates/Zeus_Widget/shared/assets/fonts/ (source-of-truth,
|
||||||
|
não duplicar — UFontFace importa como Inline e embute o .ttf no .uasset).
|
||||||
|
|
||||||
|
Nota: Typeface/TypefaceEntry/FontData NÃO são expostos ao Python (UE 5.7), então
|
||||||
|
a Composite Font (Font_Cinzel/Font_Rajdhani) não é criada por script. Como o
|
||||||
|
FUIStyleText usa um peso fixo por papel, o FSlateFontInfo referencia o FF_* direto.
|
||||||
|
|
||||||
|
Idempotente. Como rodar:
|
||||||
|
- Editor: console Python -> exec(open(r"f:/.../Scripts/import_fonts.py").read())
|
||||||
|
- Ou via MCP nwiro execute_python.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import unreal
|
||||||
|
|
||||||
|
SRC_DIR = r"f:/ZeusProject/Tools/Templates/Zeus_Widget/shared/assets/fonts"
|
||||||
|
DEST_ROOT = "/Game/ZMMO/UI/Fonts"
|
||||||
|
|
||||||
|
FAMILIES = {
|
||||||
|
"Cinzel": [
|
||||||
|
("Regular", "Cinzel-Regular.ttf"),
|
||||||
|
("SemiBold", "Cinzel-SemiBold.ttf"),
|
||||||
|
("Bold", "Cinzel-Bold.ttf"),
|
||||||
|
("ExtraBold", "Cinzel-ExtraBold.ttf"),
|
||||||
|
],
|
||||||
|
"Rajdhani": [
|
||||||
|
("Regular", "Rajdhani-Regular.ttf"),
|
||||||
|
("Medium", "Rajdhani-Medium.ttf"),
|
||||||
|
("SemiBold", "Rajdhani-SemiBold.ttf"),
|
||||||
|
("Bold", "Rajdhani-Bold.ttf"),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
|
||||||
|
|
||||||
|
|
||||||
|
def import_font_face(ttf_path, dest_pkg_path, asset_name):
|
||||||
|
task = unreal.AssetImportTask()
|
||||||
|
task.filename = ttf_path
|
||||||
|
task.destination_path = dest_pkg_path
|
||||||
|
task.destination_name = asset_name
|
||||||
|
task.replace_existing = True
|
||||||
|
task.automated = True
|
||||||
|
task.save = True
|
||||||
|
task.factory = unreal.FontFileImportFactory()
|
||||||
|
|
||||||
|
asset_tools.import_asset_tasks([task])
|
||||||
|
|
||||||
|
full = "{}/{}".format(dest_pkg_path, asset_name)
|
||||||
|
face = unreal.load_asset(full)
|
||||||
|
if face is None:
|
||||||
|
unreal.log_error("[import_fonts] FALHOU import: {}".format(full))
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
face.set_editor_property("loading_policy", unreal.FontLoadingPolicy.INLINE)
|
||||||
|
unreal.EditorAssetLibrary.save_asset(full)
|
||||||
|
except Exception as e:
|
||||||
|
unreal.log_warning("[import_fonts] loading_policy INLINE falhou em {}: {}".format(full, e))
|
||||||
|
|
||||||
|
unreal.log_warning("[import_fonts] OK {} (class={})".format(full, type(face).__name__))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
unreal.log_warning("[import_fonts] === inicio ===")
|
||||||
|
ok = 0
|
||||||
|
total = 0
|
||||||
|
for family, weights in FAMILIES.items():
|
||||||
|
dest_pkg = "{}/{}".format(DEST_ROOT, family)
|
||||||
|
for weight_name, ttf in weights:
|
||||||
|
total += 1
|
||||||
|
ttf_path = os.path.join(SRC_DIR, ttf).replace("\\", "/")
|
||||||
|
if not os.path.isfile(ttf_path):
|
||||||
|
unreal.log_error("[import_fonts] .ttf nao encontrado: {}".format(ttf_path))
|
||||||
|
continue
|
||||||
|
asset_name = "FF_{}_{}".format(family, weight_name)
|
||||||
|
if import_font_face(ttf_path, dest_pkg, asset_name):
|
||||||
|
ok += 1
|
||||||
|
unreal.log_warning("[import_fonts] === fim: {}/{} faces ===".format(ok, total))
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user