refactor: prefixo ZMMO -> Zeus em classes/módulos C++ do cliente

- Renomeia ~50 classes UCLASS/USTRUCT/UENUM/UINTERFACE pra Zeus*
  (AZeusGameMode, AZeusCharacter, UZeusGameInstance, IZeusEntityInterface,
  UZeusWorldSubsystem, FZeusEntitySnapshot, etc.)
- Encurta AZMMOPlayerCharacter -> AZeusCharacter
- Renomeia módulos satélite ZMMOAttributes -> ZeusAttributes e
  ZMMOJobs -> ZeusJobs (pasta + .Build.cs + .uproject)
- Mantém módulo principal ZMMO (renomeia depois quando jogo ganhar nome)
- DefaultEngine.ini: ActiveClassRedirects ZMMOX -> ZeusX (preserva BPs/assets)
- DefaultGame.ini: sections atualizadas pra ZeusThemeSubsystem/ZeusPlayerState
- Category="ZMMO|..." -> "Zeus|..." em UPROPERTYs
- Preserva LogZMMO, ZMMO_API, /Script/ZMMO., /Game/ZMMO/, classes Target

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 17:24:38 -03:00
parent bd1dab25ca
commit 6a6a28a086
128 changed files with 1224 additions and 1210 deletions

View File

@@ -0,0 +1,105 @@
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ZeusAttributeTypes.h"
#include "ZeusAttributeComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FZeusOnAttributesChanged, const FZeusAttributesSnapshot&, Snapshot);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZeusOnHpSpChanged, int32, Hp, int32, Sp);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZeusOnLevelUp, int32, NewBaseLevel, int32, StatusPointDelta);
/// Resposta server ao C_STAT_ALLOC. Reason e' EAllocRejectReason (None=0,
/// InvalidStat=1, InvalidAmount=2, NotEnoughPoints=3, StatCapped=4, NoSession=5).
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZeusOnStatAllocReply, bool, bAccepted, int32, Reason);
/**
* Componente de atributos do MMO ligado ao ator que o representa em-jogo
* (player local, proxies remotos, NPCs futuros).
*
* Estado authoritative vive no servidor (CharRuntimeStatus em
* Game/MMO/Modules/AttributeSystem). Cliente apenas armazena o ultimo
* snapshot recebido e expoe delegates para UI/HUD reagir.
*
* Roteamento server → componente: `UZeusAttributeNetworkHandler`
* (UWorldSubsystem) liga em `UZeusNetworkSubsystem::OnAttributeSnapshotFull`,
* resolve `EntityId -> AActor*` via `UZeusWorldSubsystem` e chama
* `ApplySnapshot` no componente do ator.
*/
UCLASS(ClassGroup=(Zeus), meta=(BlueprintSpawnableComponent),
hidecategories=(Activation, Collision, Cooking, Object, Replication))
class ZEUSATTRIBUTES_API UZeusAttributeComponent : public UActorComponent
{
GENERATED_BODY()
public:
UZeusAttributeComponent();
/// Aplica snapshot full recebido do servidor. Substitui `Current` e
/// dispara `OnAttributesChanged` + `OnHpSpChanged` (se hp/sp mudaram).
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void ApplySnapshot(const FZeusAttributesSnapshot& InSnapshot);
/// Aplica apenas delta de HP/SP (sem mexer em outros campos).
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void ApplyHpSpUpdate(int32 NewHp, int32 NewSp);
/// Notifica level up — o snapshot subsequente atualiza demais campos.
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void NotifyLevelUp(int32 NewBaseLevel, int32 StatusPointDelta);
/// Notifica resposta server ao C_STAT_ALLOC. UI pode reagir (toast/SFX
/// quando aceito, erro vermelho quando rejeitado).
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void NotifyStatAllocReply(bool bAccepted, int32 Reason);
/// Envia C_STAT_ALLOC pro server. Wrapper conveniente — busca o
/// UZeusNetworkSubsystem via GameInstance + chama SendStatAlloc.
/// `StatId`: 0=STR, 1=AGI, 2=VIT, 3=INT, 4=DEX, 5=LUK. `Amount`: 1..10.
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void RequestStatAlloc(int32 StatId, int32 Amount = 1);
/// Seed do EntityId vindo de S_SPAWN_PLAYER local. Chamado pelo
/// `AZeusCharacter` antes do primeiro S_ATTRIBUTE_SNAPSHOT_FULL
/// chegar, garantindo que o NetworkHandler consiga rotear via lookup
/// por EntityId desde o inicio.
UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
void SeedEntityId(int64 InEntityId) { Current.EntityId = InEntityId; }
UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
const FZeusAttributesSnapshot& GetSnapshot() const { return Current; }
UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
float GetHpRatio() const
{
return Current.MaxHp > 0 ? static_cast<float>(Current.Hp) / static_cast<float>(Current.MaxHp) : 0.f;
}
UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
float GetSpRatio() const
{
return Current.MaxSp > 0 ? static_cast<float>(Current.Sp) / static_cast<float>(Current.MaxSp) : 0.f;
}
// === Delegates Blueprint ===
/** Snapshot novo aplicado. Use isto na UI para refresh geral. */
UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
FZeusOnAttributesChanged OnAttributesChanged;
/** HP ou SP mudou (efêmero ou via snapshot). Para barras animadas. */
UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
FZeusOnHpSpChanged OnHpSpChanged;
/** Subiu de nível. Para efeitos visuais ("LEVEL UP!" toast). */
UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
FZeusOnLevelUp OnLevelUp;
/** Resposta ao C_STAT_ALLOC (aceito ou rejeitado). UI reage. */
UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
FZeusOnStatAllocReply OnStatAllocReply;
protected:
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes")
FZeusAttributesSnapshot Current;
};

View File

@@ -0,0 +1,51 @@
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/WorldSubsystem.h"
#include "ZeusAttributesPayload.h"
#include "ZeusAttributeNetworkHandler.generated.h"
class UZeusNetworkSubsystem;
/**
* Ponte entre o `UZeusNetworkSubsystem` (GameInstanceSubsystem do plugin
* ZeusNetwork) e os `UZeusAttributeComponent` ligados aos atores do mundo.
*
* Por que UWorldSubsystem (e nao GameInstanceSubsystem)?
* - O registry de atores (`UZeusWorldSubsystem::GetActorByEntityId`) e'
* World-scoped, reset a cada OpenLevel.
* - World subsystem so existe enquanto ha mundo carregado, o que e' exato
* quando precisamos rotear snapshots (no front-end nao ha pawn).
*
* Lifecycle: `Initialize` binda nos 3 delegates do ZeusNetworkSubsystem;
* `Deinitialize` unbinda. Conversao `FZeusAttributesPayload ->
* FZeusAttributesSnapshot` (USTRUCT Blueprint) acontece aqui.
*/
UCLASS()
class ZEUSATTRIBUTES_API UZeusAttributeNetworkHandler : public UWorldSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
private:
void HandleAttributeSnapshotFull(const FZeusAttributesPayload& Payload);
void HandleHpSpUpdate(int64 EntityId, int32 Hp, int32 Sp);
void HandleLevelUp(int64 EntityId, int32 NewBaseLevel, int32 StatusPointDelta);
void HandleStatAllocReply(bool bAccepted, int32 Reason);
UZeusNetworkSubsystem* GetZeusNetSubsystem() const;
/// Acha o AttributeComponent do player local (Pawn->PlayerState).
/// Usado pro StatAllocReply (sem EntityId no payload).
class UZeusAttributeComponent* FindLocalPlayerAttributeComponent() const;
FDelegateHandle SnapshotFullHandle;
FDelegateHandle HpSpUpdateHandle;
FDelegateHandle LevelUpHandle;
FDelegateHandle StatAllocReplyHandle;
};

View File

@@ -0,0 +1,88 @@
#pragma once
#include "CoreMinimal.h"
#include "ZeusAttributeTypes.generated.h"
/**
* Snapshot completo dos atributos do char vindo do server via
* S_ATTRIBUTE_SNAPSHOT_FULL (opcode 1500).
*
* Cliente NUNCA recalcula derivados — apenas exibe o que recebe. Os campos
* HP/MaxHp/SP/MaxSp ja sao os "efetivos" (base + equip + buff somados no
* servidor); o cliente nao ve as 3 camadas separadas.
*
* Espelha `FZeusAttributesPayload` do plugin ZeusNetwork + a serializacao
* em `Server/.../AttributeService.cpp::WriteSnapshotPayload`.
*/
USTRUCT(BlueprintType)
struct ZEUSATTRIBUTES_API FZeusAttributesSnapshot
{
GENERATED_BODY()
// === Identidade + classe ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 EntityId = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 ClassId = 0;
// === Progressao ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 BaseLevel = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 BaseExp = 0;
/** EXP pra subir o proximo base level (server resolve via JobsDatabase).
* 0 = ja' em cap -> barra cheia. % = BaseExp / BaseExpToNext. */
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 BaseExpToNext = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 JobLevel = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 JobExp = 0;
/** EXP pra subir o proximo job level. 0 = ja' em cap -> barra cheia. */
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 JobExpToNext = 0;
// === Stats primarios (Camada 1 base; efetivos vao em derivados) ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Str = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Agi = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Vit = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Int = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Dex = 1;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Stats") int32 Luk = 1;
// === Pontos nao gastos ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 StatusPoint = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 SkillPoint = 0;
// === Pool efetivo (camadas 1+2+3 somadas no servidor) ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 Hp = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 MaxHp = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 Sp = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int32 MaxSp = 0;
// === Moeda ===
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes") int64 Money = 0;
// === Derivados split em pares (base, equipBonus) ===
// Padrao RO: display mostra "ATK 51 + 0" (base + equip). Cliente NUNCA
// recalcula — servidor envia ambos prontos no S_ATTRIBUTE_SNAPSHOT_FULL.
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 AtkBase = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 AtkEquipBonus = 0;
/** MATK pre-renewal e' um range [min, max] (rathena status_base_matk_min/max).
* Display: "MATK min ~ max + equip". */
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 MatkBaseMin = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 MatkBaseMax = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 MatkEquipBonus = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 DefBase = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 DefEquipBonus = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 MdefBase = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 MdefEquipBonus = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 HitBase = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 HitEquipBonus = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 FleeBase = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 FleeEquipBonus = 0;
/** Critico × 10 internamente (10 = 1.0). Divida por 10 para exibir. */
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 CritBaseX10 = 0;
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 CritEquipBonusX10 = 0;
/** ASPD nao splita — calculo nao-linear via aspd_base × stats. Display direto. */
UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes|Derived") int32 Aspd = 0;
};

View File

@@ -0,0 +1,19 @@
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleInterface.h"
/**
* Sub-modulo cliente do AttributeSystem.
*
* Espelho de `Server/ZeusServerEngine/Game/MMO/Modules/AttributeSystem/`.
* Roda como modulo Runtime carregado em `PreDefault` para que o
* `UAttributeComponent` esteja registrado antes do `ZMMO` instanciar o
* player character.
*/
class FZeusAttributesModule : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

View File

@@ -0,0 +1,76 @@
#pragma once
#include "Blueprint/UserWidget.h"
#include "CoreMinimal.h"
#include "ZeusAttributeTypes.h"
#include "ZeusHudHpSpWidget.generated.h"
class UProgressBar;
class UTextBlock;
/**
* Sub-widget do HUD: barras de HP/SP + label de level. Sem auto-bind no
* AttributeComponent — o parent (`UZeusHudWidget`) propaga snapshots via
* `ApplySnapshot` / `ApplyHpSpDelta` quando o player local recebe updates.
*
* Composicao do HUD (ver `UZeusHudWidget`):
* WBP_HUD (UZeusHudWidget root)
* |-- HpSpBar (UZeusHudHpSpWidget — este)
* |-- PlayerInfo (futuro — nome/job/level)
* |-- Minimap (futuro)
* |-- QuickBar (futuro — hotkeys)
* |-- Buffs (futuro — icones SC)
* |-- Chat (futuro)
* |-- TargetInfo (futuro — mob/player targetado)
*
* Cada sub-widget tem responsabilidade unica (SRP). O parent (UZeusHudWidget)
* faz binding com AttributeComponent e propaga deltas.
*
* Convencao `meta=(BindWidget)`: o WBP filho deve ter widgets com nomes
* exatos (HpBar, SpBar). `BindWidgetOptional` permite omitir.
*/
UCLASS(Abstract, Blueprintable, BlueprintType)
class ZEUSATTRIBUTES_API UZeusHudHpSpWidget : public UUserWidget
{
GENERATED_BODY()
public:
/** Atualiza todos os campos a partir do snapshot. Chamado pelo UZeusHudWidget. */
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
void ApplySnapshot(const FZeusAttributesSnapshot& Snapshot);
/** Atualiza apenas HP/SP (sem mexer no level/text). Otimizacao do tick. */
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
void ApplyHpSp(int32 Hp, int32 MaxHp, int32 Sp, int32 MaxSp);
protected:
/**
* Hook BlueprintNativeEvent para skin visual reagir a um snapshot novo
* (cores, animacao de level up, etc.). Impl default em C++ apenas
* atualiza progress bars + textos via BindWidget/BindWidgetOptional.
*/
UFUNCTION(BlueprintNativeEvent, Category = "Zeus|HUD")
void OnSnapshotApplied(const FZeusAttributesSnapshot& Snapshot);
virtual void OnSnapshotApplied_Implementation(const FZeusAttributesSnapshot& Snapshot);
// === BindWidget — devem existir no WBP com EXATAMENTE estes nomes ===
UPROPERTY(BlueprintReadOnly, meta = (BindWidget), Category = "Zeus|HUD")
UProgressBar* HpBar = nullptr;
UPROPERTY(BlueprintReadOnly, meta = (BindWidget), Category = "Zeus|HUD")
UProgressBar* SpBar = nullptr;
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
UTextBlock* HpText = nullptr;
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
UTextBlock* SpText = nullptr;
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
UTextBlock* LevelText = nullptr;
private:
/// Ultimo snapshot recebido (cache pra ApplyHpSp manter MaxHp/MaxSp). */
UPROPERTY(Transient)
FZeusAttributesSnapshot LastSnapshot;
};