feat(client): AttributeSystem (Fase 1-3) + ZMMOJobs + UI in-game #3
BIN
Content/ZMMO/Data/Jobs/DA_Job_Novice.uasset
Normal file
BIN
Content/ZMMO/Data/Jobs/DA_Job_Novice.uasset
Normal file
Binary file not shown.
@@ -5,6 +5,7 @@
|
|||||||
#include "Engine/World.h"
|
#include "Engine/World.h"
|
||||||
#include "TimerManager.h"
|
#include "TimerManager.h"
|
||||||
#include "UI/Widgets/UIButton_Base.h"
|
#include "UI/Widgets/UIButton_Base.h"
|
||||||
|
#include "ZMMOJobsLibrary.h"
|
||||||
|
|
||||||
void UUICharCard_Base::NativeConstruct()
|
void UUICharCard_Base::NativeConstruct()
|
||||||
{
|
{
|
||||||
@@ -48,7 +49,7 @@ void UUICharCard_Base::SetFromSummary(const FZMMOCharSummary& InSummary)
|
|||||||
}
|
}
|
||||||
if (Text_Class)
|
if (Text_Class)
|
||||||
{
|
{
|
||||||
Text_Class->SetText(FText::FromString(FString::Printf(TEXT("Classe %d"), Summary.ClassId)));
|
Text_Class->SetText(UZMMOJobsLibrary::GetJobDisplayName(this, Summary.ClassId));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESlateVisibility ActionVis = bDeleteScheduled ? ESlateVisibility::Collapsed : ESlateVisibility::Visible;
|
const ESlateVisibility ActionVis = bDeleteScheduled ? ESlateVisibility::Collapsed : ESlateVisibility::Visible;
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ public class ZMMO : ModuleRules
|
|||||||
"CommonInput",
|
"CommonInput",
|
||||||
"GameplayTags",
|
"GameplayTags",
|
||||||
"ZeusNetwork",
|
"ZeusNetwork",
|
||||||
"ZMMOAttributes"
|
"ZMMOAttributes",
|
||||||
|
"ZMMOJobs"
|
||||||
});
|
});
|
||||||
|
|
||||||
PrivateDependencyModuleNames.AddRange(new string[] {
|
PrivateDependencyModuleNames.AddRange(new string[] {
|
||||||
|
|||||||
5
Source/ZMMOJobs/Private/ZMMOJobDataAsset.cpp
Normal file
5
Source/ZMMOJobs/Private/ZMMOJobDataAsset.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "ZMMOJobDataAsset.h"
|
||||||
|
|
||||||
|
// Implementacao vazia — todas as props sao UPROPERTY EditDefaultsOnly e
|
||||||
|
// vivem inline no .uasset. Override de GetPrimaryAssetId() esta no header
|
||||||
|
// (constexpr-friendly).
|
||||||
54
Source/ZMMOJobs/Private/ZMMOJobsLibrary.cpp
Normal file
54
Source/ZMMOJobs/Private/ZMMOJobsLibrary.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "ZMMOJobsLibrary.h"
|
||||||
|
|
||||||
|
#include "Engine/GameInstance.h"
|
||||||
|
#include "Engine/World.h"
|
||||||
|
#include "ZMMOJobDataAsset.h"
|
||||||
|
#include "ZMMOJobsSubsystem.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
/// Resolve Subsystem via WorldContextObject. Retorna nullptr em contextos
|
||||||
|
/// invalidos (CDO em editor, world em destruicao).
|
||||||
|
UZMMOJobsSubsystem* ResolveSubsystem(const UObject* WorldContextObject)
|
||||||
|
{
|
||||||
|
if (WorldContextObject == nullptr) { return nullptr; }
|
||||||
|
const UWorld* World = WorldContextObject->GetWorld();
|
||||||
|
if (World == nullptr) { return nullptr; }
|
||||||
|
UGameInstance* GI = World->GetGameInstance();
|
||||||
|
if (GI == nullptr) { return nullptr; }
|
||||||
|
return GI->GetSubsystem<UZMMOJobsSubsystem>();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
FText UZMMOJobsLibrary::GetJobDisplayName(const UObject* WorldContextObject, int32 ClassId)
|
||||||
|
{
|
||||||
|
if (UZMMOJobsSubsystem* Sub = ResolveSubsystem(WorldContextObject))
|
||||||
|
{
|
||||||
|
if (UZMMOJobDataAsset* Job = Sub->GetJobData(ClassId))
|
||||||
|
{
|
||||||
|
return Job->DisplayName.IsEmpty()
|
||||||
|
? FText::FromString(Job->TechnicalName)
|
||||||
|
: Job->DisplayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback: nao crasha UI se ClassId desconhecido.
|
||||||
|
return FText::FromString(FString::Printf(TEXT("Classe %d"), ClassId));
|
||||||
|
}
|
||||||
|
|
||||||
|
UZMMOJobDataAsset* UZMMOJobsLibrary::GetJobData(const UObject* WorldContextObject, int32 ClassId)
|
||||||
|
{
|
||||||
|
if (UZMMOJobsSubsystem* Sub = ResolveSubsystem(WorldContextObject))
|
||||||
|
{
|
||||||
|
return Sub->GetJobData(ClassId);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UZMMOJobsLibrary::IsJobRegistered(const UObject* WorldContextObject, int32 ClassId)
|
||||||
|
{
|
||||||
|
if (UZMMOJobsSubsystem* Sub = ResolveSubsystem(WorldContextObject))
|
||||||
|
{
|
||||||
|
return Sub->GetJobData(ClassId) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
13
Source/ZMMOJobs/Private/ZMMOJobsModule.cpp
Normal file
13
Source/ZMMOJobs/Private/ZMMOJobsModule.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "ZMMOJobsModule.h"
|
||||||
|
|
||||||
|
#include "Modules/ModuleManager.h"
|
||||||
|
|
||||||
|
void FZMMOJobsModule::StartupModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FZMMOJobsModule::ShutdownModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_MODULE(FZMMOJobsModule, ZMMOJobs)
|
||||||
67
Source/ZMMOJobs/Private/ZMMOJobsSubsystem.cpp
Normal file
67
Source/ZMMOJobs/Private/ZMMOJobsSubsystem.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "ZMMOJobsSubsystem.h"
|
||||||
|
|
||||||
|
#include "AssetRegistry/AssetRegistryModule.h"
|
||||||
|
#include "Modules/ModuleManager.h"
|
||||||
|
#include "ZMMOJobDataAsset.h"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY_STATIC(LogZMMOJobs, Log, All);
|
||||||
|
|
||||||
|
void UZMMOJobsSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
|
{
|
||||||
|
Super::Initialize(Collection);
|
||||||
|
LoadJobsFromAssetRegistry();
|
||||||
|
UE_LOG(LogZMMOJobs, Log, TEXT("[ZMMOJobsSubsystem] Initialize: %d job(s) carregados"), CachedJobs.Num());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOJobsSubsystem::Deinitialize()
|
||||||
|
{
|
||||||
|
CachedJobs.Empty();
|
||||||
|
Super::Deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOJobsSubsystem::LoadJobsFromAssetRegistry()
|
||||||
|
{
|
||||||
|
FAssetRegistryModule& AssetRegistryModule =
|
||||||
|
FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
|
||||||
|
IAssetRegistry& AR = AssetRegistryModule.Get();
|
||||||
|
|
||||||
|
// Editor pode chamar antes de scan inicial. Standalone/PIE scan ja' rodou.
|
||||||
|
// SearchAllAssets(false) = nao-blocking; assume cache populado em runtime.
|
||||||
|
#if WITH_EDITOR
|
||||||
|
AR.SearchAllAssets(true); // bloqueia editor; ok em Initialize
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TArray<FAssetData> Assets;
|
||||||
|
const FTopLevelAssetPath ClassPath(UZMMOJobDataAsset::StaticClass()->GetClassPathName());
|
||||||
|
AR.GetAssetsByClass(ClassPath, Assets, /*bSearchSubClasses*/ true);
|
||||||
|
|
||||||
|
for (const FAssetData& AssetData : Assets)
|
||||||
|
{
|
||||||
|
UZMMOJobDataAsset* Job = Cast<UZMMOJobDataAsset>(AssetData.GetAsset());
|
||||||
|
if (Job == nullptr) { continue; }
|
||||||
|
|
||||||
|
if (CachedJobs.Contains(Job->ClassId))
|
||||||
|
{
|
||||||
|
UE_LOG(LogZMMOJobs, Warning,
|
||||||
|
TEXT("[ZMMOJobsSubsystem] Duplicate ClassId=%d (existing=%s, new=%s) — ignorando segundo"),
|
||||||
|
Job->ClassId,
|
||||||
|
*CachedJobs[Job->ClassId]->GetName(),
|
||||||
|
*Job->GetName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedJobs.Add(Job->ClassId, Job);
|
||||||
|
UE_LOG(LogZMMOJobs, Verbose,
|
||||||
|
TEXT("[ZMMOJobsSubsystem] Cached classId=%d name=%s display=%s"),
|
||||||
|
Job->ClassId, *Job->TechnicalName, *Job->DisplayName.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UZMMOJobDataAsset* UZMMOJobsSubsystem::GetJobData(int32 ClassId) const
|
||||||
|
{
|
||||||
|
if (const TObjectPtr<UZMMOJobDataAsset>* Found = CachedJobs.Find(ClassId))
|
||||||
|
{
|
||||||
|
return Found->Get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
75
Source/ZMMOJobs/Public/ZMMOJobDataAsset.h
Normal file
75
Source/ZMMOJobs/Public/ZMMOJobDataAsset.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Engine/DataAsset.h"
|
||||||
|
#include "ZMMOJobDataAsset.generated.h"
|
||||||
|
|
||||||
|
class UTexture2D;
|
||||||
|
class USoundBase;
|
||||||
|
class UAnimInstance;
|
||||||
|
class UAnimMontage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dados visuais/UI de UM job (classe). 1 .uasset por job em
|
||||||
|
* `Content/ZMMO/Data/Jobs/DA_Job_<Nome>.uasset`.
|
||||||
|
*
|
||||||
|
* ClassId eh a CHAVE — bate com `classId` do snapshot do server (rathena
|
||||||
|
* pc.hpp `job_class`, ex: Novice=0, Swordsman=1, Mage=2, ...).
|
||||||
|
*
|
||||||
|
* Soft pointers (TSoftObjectPtr) sao usados pra assets pesados (textures,
|
||||||
|
* sounds) — lazy-loaded quando precisar (level up, hover icon). DataAsset
|
||||||
|
* em si fica em memoria depois do scan do Subsystem.
|
||||||
|
*
|
||||||
|
* Async pointers (TSubclassOf) sao sync — anim BP precisa estar carregada
|
||||||
|
* quando o player spawna.
|
||||||
|
*/
|
||||||
|
UCLASS(BlueprintType)
|
||||||
|
class ZMMOJOBS_API UZMMOJobDataAsset : public UPrimaryDataAsset
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Chave estavel (bate com `Config/Jobs/<Name>.json:Id` no server e com
|
||||||
|
/// `FZMMOAttributesSnapshot::ClassId` recebido do server).
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job")
|
||||||
|
int32 ClassId = 0;
|
||||||
|
|
||||||
|
/// Nome tecnico estavel (en-US). Ex: "Novice", "Swordsman". Aparece em
|
||||||
|
/// logs e telemetria — NUNCA exibido pro player.
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job")
|
||||||
|
FString TechnicalName;
|
||||||
|
|
||||||
|
/// Nome localizado exibido na UI (pt-BR no projeto base). Ex: "Aprendiz".
|
||||||
|
/// Pode usar FText Localization tables pra multi-idioma futuro.
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job")
|
||||||
|
FText DisplayName;
|
||||||
|
|
||||||
|
/// Icone do job — usado em StatusWindow, CharacterCard, JobChangeUI.
|
||||||
|
/// Soft ptr: nao carrega ate alguem chamar LoadSynchronous() ou async load.
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job|Assets")
|
||||||
|
TSoftObjectPtr<UTexture2D> JobIcon;
|
||||||
|
|
||||||
|
/// AnimInstance class override (opcional). Quando nao-null, AnimBP
|
||||||
|
/// padrao do PlayerCharacter eh substituido por esta classe no spawn
|
||||||
|
/// (jobs com move set diferente — Monge bate, Assassin furtivo, etc.).
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job|Anim")
|
||||||
|
TSubclassOf<UAnimInstance> DefaultAnimInstanceClass;
|
||||||
|
|
||||||
|
/// Montage de "job change" (animacao de transformacao). Tocada quando
|
||||||
|
/// player promove de Novice → 1a classe. V1 nao implementado.
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job|Anim")
|
||||||
|
TSoftObjectPtr<UAnimMontage> JobChangeMontage;
|
||||||
|
|
||||||
|
/// Som de level up override. Quando null, HUD usa som generico do projeto.
|
||||||
|
/// Soft ptr: lazy load no primeiro level up.
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Zeus|Job|Audio")
|
||||||
|
TSoftObjectPtr<USoundBase> LevelUpSoundCue;
|
||||||
|
|
||||||
|
/// PrimaryAssetType pro AssetManager (precisa pra GetPrimaryAssetIdList).
|
||||||
|
/// Hardcoded "ZMMOJob" — registry classifica todos os DAs deste tipo.
|
||||||
|
virtual FPrimaryAssetId GetPrimaryAssetId() const override
|
||||||
|
{
|
||||||
|
return FPrimaryAssetId(FPrimaryAssetType(TEXT("ZMMOJob")),
|
||||||
|
*FString::Printf(TEXT("Job_%d_%s"), ClassId, *TechnicalName));
|
||||||
|
}
|
||||||
|
};
|
||||||
39
Source/ZMMOJobs/Public/ZMMOJobsLibrary.h
Normal file
39
Source/ZMMOJobs/Public/ZMMOJobsLibrary.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
|
#include "ZMMOJobsLibrary.generated.h"
|
||||||
|
|
||||||
|
class UZMMOJobDataAsset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers Blueprint pra UI/HUD acessar dados de job sem precisar pegar o
|
||||||
|
* Subsystem manualmente. Todos usam WorldContextObject pra resolver
|
||||||
|
* GameInstance → Subsystem internamente.
|
||||||
|
*
|
||||||
|
* Padrao de uso em UMG:
|
||||||
|
* - Text binding: `JobsLibrary::GetJobDisplayName(Self, AttrComp.Current.ClassId)`
|
||||||
|
* - Image binding: `JobsLibrary::GetJobIcon(Self, ClassId).LoadSynchronous()`
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class ZMMOJOBS_API UZMMOJobsLibrary : public UBlueprintFunctionLibrary
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Nome localizado do job. Fallback "Classe N" se ClassId nao tem DA
|
||||||
|
/// correspondente (job nao registrado no Content/ZMMO/Data/Jobs/).
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Zeus|Jobs",
|
||||||
|
meta = (WorldContext = "WorldContextObject"))
|
||||||
|
static FText GetJobDisplayName(const UObject* WorldContextObject, int32 ClassId);
|
||||||
|
|
||||||
|
/// DataAsset completo (pode ser nullptr — caller checa).
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Zeus|Jobs",
|
||||||
|
meta = (WorldContext = "WorldContextObject"))
|
||||||
|
static UZMMOJobDataAsset* GetJobData(const UObject* WorldContextObject, int32 ClassId);
|
||||||
|
|
||||||
|
/// Helper de UI: retorna true se ClassId tem DA registrado.
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Zeus|Jobs",
|
||||||
|
meta = (WorldContext = "WorldContextObject"))
|
||||||
|
static bool IsJobRegistered(const UObject* WorldContextObject, int32 ClassId);
|
||||||
|
};
|
||||||
23
Source/ZMMOJobs/Public/ZMMOJobsModule.h
Normal file
23
Source/ZMMOJobs/Public/ZMMOJobsModule.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Modules/ModuleInterface.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-modulo cliente do JobsSystem.
|
||||||
|
*
|
||||||
|
* Espelho de `Server/ZeusServerEngine/Game/MMO/Modules/JobsSystem/`. Roda
|
||||||
|
* como modulo Runtime em LoadingPhase PreDefault para que o
|
||||||
|
* `UZMMOJobsSubsystem` esteja registrado antes do ZMMO core spawnar a HUD.
|
||||||
|
*
|
||||||
|
* Responsabilidades:
|
||||||
|
* - Dados visuais por job: DisplayName localizado, JobIcon, anim override
|
||||||
|
* - Lookup classId → UZMMOJobDataAsset via Subsystem
|
||||||
|
* - Library Blueprint pra HUD/UI consumir
|
||||||
|
*/
|
||||||
|
class FZMMOJobsModule : public IModuleInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void StartupModule() override;
|
||||||
|
virtual void ShutdownModule() override;
|
||||||
|
};
|
||||||
52
Source/ZMMOJobs/Public/ZMMOJobsSubsystem.h
Normal file
52
Source/ZMMOJobs/Public/ZMMOJobsSubsystem.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Subsystems/GameInstanceSubsystem.h"
|
||||||
|
#include "ZMMOJobsSubsystem.generated.h"
|
||||||
|
|
||||||
|
class UZMMOJobDataAsset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache central de UZMMOJobDataAsset por ClassId. Vive como GameInstance
|
||||||
|
* Subsystem — startup automatico quando GameInstance inicializa (PIE,
|
||||||
|
* standalone, packaged). Sobrevive a map transitions.
|
||||||
|
*
|
||||||
|
* Initialize:
|
||||||
|
* 1. Carrega via AssetRegistry: scan de UZMMOJobDataAsset em todo Content
|
||||||
|
* 2. Cacheia em TMap<int32, UZMMOJobDataAsset*> por ClassId
|
||||||
|
* 3. Log: quantos jobs encontrou
|
||||||
|
*
|
||||||
|
* Uso:
|
||||||
|
* - C++: GameInstance->GetSubsystem<UZMMOJobsSubsystem>()->GetJobData(0)
|
||||||
|
* - BP: UZMMOJobsLibrary::GetJobData(WorldContext, 0)
|
||||||
|
*
|
||||||
|
* Fase 7+ (Mod support): SCANEAR PrimaryAssetType="ZMMOJob" do AssetManager
|
||||||
|
* permite mods adicionarem DAs proprios sem mexer no source.
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class ZMMOJOBS_API UZMMOJobsSubsystem : public UGameInstanceSubsystem
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||||
|
virtual void Deinitialize() override;
|
||||||
|
|
||||||
|
/// Lookup por classId. Retorna nullptr se ClassId nao tem DA correspondente
|
||||||
|
/// (caller usa Library com fallback FText).
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Zeus|Jobs")
|
||||||
|
UZMMOJobDataAsset* GetJobData(int32 ClassId) const;
|
||||||
|
|
||||||
|
/// Total de jobs cacheados (diagnostico).
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Zeus|Jobs")
|
||||||
|
int32 GetJobCount() const { return CachedJobs.Num(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Scan AssetRegistry + popula CachedJobs. Sincronizo (V1) — chamado UMA
|
||||||
|
/// vez no Initialize. Pra 50 jobs eh aceitavel; se crescer pra 200+ pode
|
||||||
|
/// virar async no futuro.
|
||||||
|
void LoadJobsFromAssetRegistry();
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TMap<int32, TObjectPtr<UZMMOJobDataAsset>> CachedJobs;
|
||||||
|
};
|
||||||
26
Source/ZMMOJobs/ZMMOJobs.Build.cs
Normal file
26
Source/ZMMOJobs/ZMMOJobs.Build.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using UnrealBuildTool;
|
||||||
|
|
||||||
|
public class ZMMOJobs : ModuleRules
|
||||||
|
{
|
||||||
|
public ZMMOJobs(ReadOnlyTargetRules Target) : base(Target)
|
||||||
|
{
|
||||||
|
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||||
|
|
||||||
|
PublicDependencyModuleNames.AddRange(new string[] {
|
||||||
|
"Core",
|
||||||
|
"CoreUObject",
|
||||||
|
"Engine"
|
||||||
|
});
|
||||||
|
|
||||||
|
PrivateDependencyModuleNames.AddRange(new string[] {
|
||||||
|
"AssetRegistry" // FAssetRegistryModule pra scan de DA_Job_*
|
||||||
|
});
|
||||||
|
|
||||||
|
// Espelho do `Server/.../JobsSystem/module.json` (modulo nucleo MMO).
|
||||||
|
// Cliente roda em LoadingPhase PreDefault — Subsystem inicializa
|
||||||
|
// ANTES de o ZMMO core criar a player character / HUD.
|
||||||
|
//
|
||||||
|
// Sem dependencia em ZMMOAttributes: server envia classId no snapshot,
|
||||||
|
// cliente faz lookup local. Mantem o peer-module pattern.
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Source/ZMMOJobs/module.json
Normal file
18
Source/ZMMOJobs/module.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "ZMMOJobs",
|
||||||
|
"gameType": "MMO",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"side": "client",
|
||||||
|
"dependencies": {
|
||||||
|
"engine": ["Core", "CoreUObject", "Engine", "AssetRegistry"],
|
||||||
|
"modules": []
|
||||||
|
},
|
||||||
|
"publicHeaders": [
|
||||||
|
"ZMMOJobsModule.h",
|
||||||
|
"ZMMOJobDataAsset.h",
|
||||||
|
"ZMMOJobsSubsystem.h",
|
||||||
|
"ZMMOJobsLibrary.h"
|
||||||
|
],
|
||||||
|
"loadingPhase": "PreDefault",
|
||||||
|
"description": "Sub-modulo cliente do GameType MMO — dados visuais/UI por job (DisplayName localizado, ícone, anim override, som de level up). Espelha JobsSystem do server mas focado em apresentacao. NAO depende de ZMMOAttributes — server envia classId no snapshot, cliente faz lookup local. Pattern peer-module estabelecido no PR #9."
|
||||||
|
}
|
||||||
@@ -13,6 +13,11 @@
|
|||||||
"Name": "ZMMOAttributes",
|
"Name": "ZMMOAttributes",
|
||||||
"Type": "Runtime",
|
"Type": "Runtime",
|
||||||
"LoadingPhase": "PreDefault"
|
"LoadingPhase": "PreDefault"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ZMMOJobs",
|
||||||
|
"Type": "Runtime",
|
||||||
|
"LoadingPhase": "PreDefault"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Plugins": [
|
"Plugins": [
|
||||||
|
|||||||
Reference in New Issue
Block a user