feat(combat): cues de hit react + som punch + camera shake (cliente UE)
3 GameplayCueNotify_Burst BPs (taxonomia Lyra GameplayCue.Zeus.Combat.Hit.*): GC_Combat_Hit_React -> PlayAnimMontage AM_HitReact_Light no alvo GC_Combat_Hit_Impact -> SpawnSoundAtLocation SW_Punch_Cartoon na pos do alvo GC_Combat_Hit_Self -> ClientStartCameraShake CS_HitReact no PC do alvo Assets novos: AS_HitReact (+ AM_HitReact_Light/Medium/Heavy) -- montages de reacao SW_Punch_Cartoon -- SFX de impacto (0.3s) CS_HitReact -- LegacyCameraShake (osc 0.35s, pitch/roll/locZ) DT_Abilities recriado (RowStruct ZeusAbilityDataRow): rows Dash+Kick com AbilityClass + ActivateCueTag GameplayCue.Zeus.*. GC_Kick/GC_Dash com tags renomeadas pro prefixo GameplayCue.* (filter do Asset Picker). ZeusServerTags.ini: regenerado via ZeusTool tags sync (106 tags canonicas). Source/Combat/ZeusAnimNotifyState_BodyHitWindow: AnimNotifyState que abre a janela de hit detection (FootR capsule) durante o swing do Kick. GC_Kick_Target removido (substituido por Combat.Hit.React reutilizavel). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// Copyright Zeus Server Engine. All rights reserved.
|
||||
|
||||
#include "ZeusAnimNotifyState_BodyHitWindow.h"
|
||||
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Game/Entity/ZeusCharacter.h"
|
||||
|
||||
void UZeusAnimNotifyState_BodyHitWindow::NotifyBegin(USkeletalMeshComponent* MeshComp,
|
||||
UAnimSequenceBase* /*Animation*/, float /*TotalDuration*/,
|
||||
const FAnimNotifyEventReference& /*EventReference*/)
|
||||
{
|
||||
if (!MeshComp) { return; }
|
||||
if (AZeusCharacter* Char = Cast<AZeusCharacter>(MeshComp->GetOwner()))
|
||||
{
|
||||
Char->SetHitColliderEnabled(Source, /*bEnabled*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
void UZeusAnimNotifyState_BodyHitWindow::NotifyEnd(USkeletalMeshComponent* MeshComp,
|
||||
UAnimSequenceBase* /*Animation*/, const FAnimNotifyEventReference& /*EventReference*/)
|
||||
{
|
||||
if (!MeshComp) { return; }
|
||||
if (AZeusCharacter* Char = Cast<AZeusCharacter>(MeshComp->GetOwner()))
|
||||
{
|
||||
Char->SetHitColliderEnabled(Source, /*bEnabled*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
FString UZeusAnimNotifyState_BodyHitWindow::GetNotifyName_Implementation() const
|
||||
{
|
||||
const TCHAR* SourceLabel;
|
||||
switch (Source)
|
||||
{
|
||||
case EZeusHitSource::FootR: SourceLabel = TEXT("FootR"); break;
|
||||
case EZeusHitSource::FootL: SourceLabel = TEXT("FootL"); break;
|
||||
case EZeusHitSource::HandR: SourceLabel = TEXT("HandR"); break;
|
||||
case EZeusHitSource::HandL: SourceLabel = TEXT("HandL"); break;
|
||||
case EZeusHitSource::WeaponR: SourceLabel = TEXT("WeaponR"); break;
|
||||
case EZeusHitSource::WeaponL: SourceLabel = TEXT("WeaponL"); break;
|
||||
default: SourceLabel = TEXT("?"); break;
|
||||
}
|
||||
return FString::Printf(TEXT("Zeus Body Hit (%s)"), SourceLabel);
|
||||
}
|
||||
#endif
|
||||
74
Source/ZMMO/Game/Combat/ZeusAnimNotifyState_BodyHitWindow.h
Normal file
74
Source/ZMMO/Game/Combat/ZeusAnimNotifyState_BodyHitWindow.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright Zeus Server Engine. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimNotifies/AnimNotifyState.h"
|
||||
#include "Game/Entity/ZeusCharacter.h" // EZeusHitSource
|
||||
#include "ZeusAnimNotifyState_BodyHitWindow.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UAnimSequenceBase;
|
||||
|
||||
/**
|
||||
* AnimNotifyState que liga o HitCollider de uma parte do corpo durante a sua
|
||||
* janela no montage. NotifyBegin liga + NotifyEnd desliga -- define o HIT
|
||||
* WINDOW do golpe melee/arma branca.
|
||||
*
|
||||
* Generaliza para qualquer parte do corpo via EZeusHitSource:
|
||||
* - FootR / FootL -> chute (capsule attachado em foot_*_Socket)
|
||||
* - HandR / HandL -> soco (capsule em HandGrip_*)
|
||||
* - WeaponR / WeaponL -> arma branca (capsule em weapon_*)
|
||||
*
|
||||
* === Como usar ===
|
||||
*
|
||||
* No editor de um AnimMontage (ex: AM_Kick_Montage):
|
||||
* 1. Encontrar o frame onde o membro comeca o movimento de impacto.
|
||||
* 2. Right-click na track de notifies -> Add Notify State -> Zeus Body Hit Window.
|
||||
* 3. Definir Source = FootR (ou HandR pra soco, WeaponR pra arma, etc).
|
||||
* 4. Arrastar o range pra cobrir o arco completo do golpe (ex: frame 8 a 18
|
||||
* em 30fps = ~330ms de janela).
|
||||
*
|
||||
* Pq AnimNotifyState e nao AnimNotify pontual:
|
||||
* - AnimNotify dispara em UM frame -> nao da' pra detectar entradas no
|
||||
* capsule durante a janela.
|
||||
* - AnimNotifyState tem NotifyBegin/NotifyTick/NotifyEnd. Pra "ligar
|
||||
* collider de frame X ate Y", e' o pattern correto.
|
||||
*
|
||||
* === Replicacao ===
|
||||
*
|
||||
* Roda LOCAL em cada cliente. Cliente do ATIVADOR liga capsule local + reporta
|
||||
* overlap via opcode MELEE_HIT_REPORT pro server. Server valida e aplica dano +
|
||||
* dispatcha cue Kick.Target pra todos no AOI do alvo.
|
||||
*
|
||||
* Proxies de outros clientes tocam o montage via GameplayCue replicado (visual)
|
||||
* mas o capsule deles roda no PROXY que e' Pawn local de outra coisa -- nao
|
||||
* importa, o reportador autoritativo eh quem ativou a ability.
|
||||
*/
|
||||
UCLASS(meta = (DisplayName = "Zeus Body Hit Window"))
|
||||
class ZMMO_API UZeusAnimNotifyState_BodyHitWindow : public UAnimNotifyState
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/// Qual parte do corpo (capsule) tem o hit ligado durante a janela.
|
||||
/// Default = FootR (chute direito e' o golpe mais comum em montages
|
||||
/// melee unarmed). Trocar pra HandR pra soco, WeaponR pra arma, etc.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Zeus|Combat")
|
||||
EZeusHitSource Source = EZeusHitSource::FootR;
|
||||
|
||||
// === AnimNotifyState overrides ===
|
||||
|
||||
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
|
||||
float TotalDuration, const FAnimNotifyEventReference& EventReference) override;
|
||||
|
||||
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
|
||||
const FAnimNotifyEventReference& EventReference) override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
/// Mostra "Zeus Body Hit (FootR/HandL/WeaponR/...)" no editor de montage em
|
||||
/// vez do nome generico da classe -- ajuda a identificar qual parte sem
|
||||
/// abrir details.
|
||||
virtual FString GetNotifyName_Implementation() const override;
|
||||
#endif
|
||||
};
|
||||
Reference in New Issue
Block a user