Files
ZMMO/Source/ZMMOJobs/Private/ZMMOJobsSubsystem.cpp
Mateus Rodrigues 6391372f00 feat(jobs): Jobs.1 client UI infra (handler + library + tecla J) + UI tweaks
Infraestrutura cliente da promocao de classe (Jobs.1). WBP_JobChangePanel
NAO esta neste commit — foi exploracao descartada (criar UI dinamica de
botoes via MCP BP graph esbarrou em limites do CreateWidget node). A
fundacao C++ fica pronta pra ser usada quando voltarmos pra UI.

INFRA C++ NOVA (Source/ZMMOJobs/)
* UZMMOJobChangeNetworkHandler (WorldSubsystem novo) — bind no
  OnJobChangeResult do plugin e re-broadcast via FZMMOOnJobChangeResultBP
  (dynamic multicast assignavel em BP). WBP futura escuta direto.
* UZMMOJobsSubsystem helpers: GetJobsByTier(EZMMOJobTier) +
  GetEligibleNextJobs(currentClassId) — filtra por ParentClassId. Pure.
* UZMMOJobsLibrary BPFL wrappers + SendJobChangeRequest convenience
  (delega pro UZeusNetworkSubsystem). Dep ZeusNetwork adicionada no
  Build.cs.

ENUM + INPUT
* EZMMOInGameUIState ganha JobChangePanel (entre StatusWindow e
  Inventory). DA_InGameScreenSet pendente de receber entry quando
  WBP for criada (tecla J vai falhar silenciosamente ate la).
* ZMMOPlayerController: tecla J -> ToggleJobChangePanel ->
  Flow->ToggleScreen(JobChangePanel). Espelha pattern do Alt+A do
  StatusWindow (InputComponent legacy BindKey + FInputChord).

UI TWEAKS
* WBP_StatusWindow + DT_UI_Styles: ajustes visuais no Editor durante a
  sessao (sem mudanca funcional documentavel — provavelmente fontes/
  spacing/cores).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 01:37:04 -03:00

97 lines
2.7 KiB
C++

#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;
}
TArray<UZMMOJobDataAsset*> UZMMOJobsSubsystem::GetJobsByTier(EZMMOJobTier Tier) const
{
TArray<UZMMOJobDataAsset*> Out;
Out.Reserve(CachedJobs.Num());
for (const TPair<int32, TObjectPtr<UZMMOJobDataAsset>>& Pair : CachedJobs)
{
if (Pair.Value && Pair.Value->Tier == Tier)
{
Out.Add(Pair.Value.Get());
}
}
return Out;
}
TArray<UZMMOJobDataAsset*> UZMMOJobsSubsystem::GetEligibleNextJobs(int32 CurrentClassId) const
{
TArray<UZMMOJobDataAsset*> Out;
Out.Reserve(4); // tipico: 2-6 destinos
for (const TPair<int32, TObjectPtr<UZMMOJobDataAsset>>& Pair : CachedJobs)
{
if (Pair.Value && Pair.Value->ParentClassId == CurrentClassId
&& Pair.Value->ClassId != CurrentClassId)
{
Out.Add(Pair.Value.Get());
}
}
return Out;
}