第一次提交
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Weapon/GCS_WeaponActor.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "GCS_LogChannels.h"
|
||||
#include "Collision/GCS_TraceSystemComponent.h"
|
||||
#include "Misc/DataValidation.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
#include "Net/Core/PushModel/PushModel.h"
|
||||
|
||||
AGCS_WeaponActor::AGCS_WeaponActor(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
bReplicates = true;
|
||||
bWeaponActive = false;
|
||||
}
|
||||
|
||||
APawn* AGCS_WeaponActor::GetWeaponOwner_Implementation() const
|
||||
{
|
||||
return Cast<APawn>(GetOwner());
|
||||
}
|
||||
|
||||
const FGameplayTagContainer AGCS_WeaponActor::GetWeaponTags_Implementation() const
|
||||
{
|
||||
return WeaponTags;
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
FDoRepLifetimeParams Parameters;
|
||||
Parameters.bIsPushBased = true;
|
||||
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ThisClass, bWeaponActive, Parameters)
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::SetWeaponActive_Implementation(bool bNewActive)
|
||||
{
|
||||
if (GetOwner()->HasAuthority())
|
||||
{
|
||||
const bool prev = bWeaponActive;
|
||||
bWeaponActive = bNewActive;
|
||||
MARK_PROPERTY_DIRTY_FROM_NAME(ThisClass, bWeaponActive, this);
|
||||
OnWeaponActiveStateChanged(prev);
|
||||
}
|
||||
}
|
||||
|
||||
bool AGCS_WeaponActor::IsWeaponActive_Implementation() const
|
||||
{
|
||||
return bWeaponActive;
|
||||
}
|
||||
|
||||
UPrimitiveComponent* AGCS_WeaponActor::GetPrimitiveComponent_Implementation() const
|
||||
{
|
||||
if (WeaponMeshTagName.IsValid())
|
||||
{
|
||||
UPrimitiveComponent* Primitive = Cast<UPrimitiveComponent>(GetOwner()->FindComponentByTag(UPrimitiveComponent::StaticClass(), WeaponMeshTagName));
|
||||
if (!IsValid(Primitive))
|
||||
{
|
||||
GCS_CLOG(Warning, "failed to find weapon mesh via tag (%s) as weapon primitive component. weapon owner:%s",
|
||||
*WeaponMeshTagName.ToString(),
|
||||
*GetOwner()->GetName());
|
||||
return nullptr;
|
||||
}
|
||||
return Primitive;
|
||||
}
|
||||
GCS_CLOG(Warning, "no weapon primitive component provided. weapon owner:%s", *GetOwner()->GetName());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const
|
||||
{
|
||||
TagContainer = Execute_GetWeaponTags(this);
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::OnWeaponActiveStateChanged_Implementation(bool Prev)
|
||||
{
|
||||
OnWeaponActiveStateChangedEvent.Broadcast(bWeaponActive);
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
if (Execute_IsWeaponActive(this))
|
||||
{
|
||||
bWeaponActive = false;
|
||||
RefreshTraceInstance();
|
||||
}
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::RefreshTraceInstance_Implementation()
|
||||
{
|
||||
APawn* Pawn = Execute_GetWeaponOwner(this);
|
||||
if (!IsValid(Pawn))
|
||||
{
|
||||
GCS_CLOG(Warning, "mising weapon owner!")
|
||||
return;
|
||||
}
|
||||
UGCS_TraceSystemComponent* TSC = UGCS_TraceSystemComponent::GetTraceSystemComponent(Pawn);
|
||||
if (!IsValid(TSC))
|
||||
{
|
||||
GCS_CLOG(Warning, "missing trace system on weapon owner(%s)!", *GetNameSafe(Pawn))
|
||||
return;
|
||||
}
|
||||
if (bWeaponActive)
|
||||
{
|
||||
TraceHandles.Reset();
|
||||
for (const FGCS_TraceDefinition& TraceDefinition : TraceDefinitions)
|
||||
{
|
||||
UPrimitiveComponent* Primitive = GetSourceComponentForTrace(TraceDefinition.TraceTag);
|
||||
if (Primitive == nullptr)
|
||||
{
|
||||
GCS_CLOG(Error, "No SourceComponent provided for trace:%s,check your GetSourceComponentForTrace implementation.", *TraceDefinition.TraceTag.ToString());
|
||||
continue;
|
||||
}
|
||||
FGCS_TraceHandle Handle = TSC->AddTrace(TraceDefinition, Primitive, GetSourceObjectForTrace());
|
||||
if (Handle.IsValidHandle())
|
||||
{
|
||||
TraceHandles.Add(Handle);
|
||||
}
|
||||
}
|
||||
TSC->OnTraceHitEvent.AddDynamic(this, &ThisClass::OnAnyTraceHit);
|
||||
TSC->OnTraceStateChangedEvent.AddDynamic(this, &ThisClass::OnAnyTraceStateChanged);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSC->OnTraceHitEvent.RemoveDynamic(this, &ThisClass::OnAnyTraceHit);
|
||||
TSC->OnTraceStateChangedEvent.RemoveDynamic(this, &ThisClass::OnAnyTraceStateChanged);
|
||||
for (const FGCS_TraceHandle& TraceHandle : TraceHandles)
|
||||
{
|
||||
TSC->RemoveTrace(TraceHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UObject* AGCS_WeaponActor::GetSourceObjectForTrace_Implementation()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
UPrimitiveComponent* AGCS_WeaponActor::GetSourceComponentForTrace_Implementation(const FGameplayTag& TraceTag) const
|
||||
{
|
||||
// Default Using weapon primitive as source component for trace
|
||||
if (UPrimitiveComponent* PrimitiveComponent = Execute_GetPrimitiveComponent(this))
|
||||
{
|
||||
return PrimitiveComponent;
|
||||
}
|
||||
|
||||
GCS_CLOG(Error, "Weapon(%s) didn't return return valid primitive component to be used as SourceComponent for traces, try implement this function to get properly SourceComponent For Trace.",
|
||||
*GetNameSafe(this))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::OnAnyTraceHit_Implementation(const FGCS_TraceHandle& TraceHandle, const FHitResult& HitResult)
|
||||
{
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::OnAnyTraceStateChanged_Implementation(const FGCS_TraceHandle& TraceHandle, bool NewState)
|
||||
{
|
||||
}
|
||||
|
||||
void AGCS_WeaponActor::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
EDataValidationResult AGCS_WeaponActor::IsDataValid(class FDataValidationContext& Context) const
|
||||
{
|
||||
for (int32 i = 0; i < TraceDefinitions.Num(); i++)
|
||||
{
|
||||
if (!TraceDefinitions[i].IsValidDefinition())
|
||||
{
|
||||
Context.AddWarning(FText::FromString(FString::Format(TEXT("Found invalid trace definition at index({0})"), {i})));
|
||||
return EDataValidationResult::Invalid;
|
||||
}
|
||||
}
|
||||
return Super::IsDataValid(Context);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user