第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/Flying/GMS_FlyingMode.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_FlyingMode)

View File

@@ -0,0 +1,6 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/GMS_MoverSettingObjectLibrary.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_MoverSettingObjectLibrary)

View File

@@ -0,0 +1,6 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/GMS_MoverStructLibrary.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_MoverStructLibrary)

View File

@@ -0,0 +1,150 @@
// // Copyright 2025 https://yuewu.dev/en All Rights Reserved.
//
//
// #include "Mover/Modifers/GMS_MovementStateModifer.h"
//
// #include "MoverComponent.h"
// #include "DefaultMovementSet/Settings/CommonLegacyMovementSettings.h"
// #include "MoveLibrary/MovementUtils.h"
// #include "Mover/GMS_MoverStructLibrary.h"
//
//
// FGMS_MovementStateModifier::FGMS_MovementStateModifier()
// {
// DurationMs = -1.0f;
// }
//
// void FGMS_MovementStateModifier::OnStart(UMoverComponent* MoverComp, const FMoverTimeStep& TimeStep, const FMoverSyncState& SyncState, const FMoverAuxStateContext& AuxState)
// {
// const FGMS_MoverMovementControlInputs* Inputs = SyncState.SyncStateCollection.FindMutableDataByType<FGMS_MoverMovementControlInputs>();
//
// if (UStanceSettings* StanceSettings = MoverComp->FindSharedSettings_Mutable<UStanceSettings>())
// {
// if (const UCapsuleComponent* CapsuleComponent = Cast<UCapsuleComponent>(MoverComp->GetUpdatedComponent()))
// {
// float OldHalfHeight = CapsuleComponent->GetScaledCapsuleHalfHeight();
// float NewHalfHeight = 0;
// float NewEyeHeight = 0;
//
// switch (ActiveStance)
// {
// default:
// case EStanceMode::Crouch:
// NewHalfHeight = StanceSettings->CrouchHalfHeight;
// NewEyeHeight = StanceSettings->CrouchedEyeHeight;
// break;
//
// // Prone isn't currently implemented
// case EStanceMode::Prone:
// UE_LOG(LogMover, Warning, TEXT("Stance got into prone stance - That stance is not currently implemented."));
// // TODO: returning here so we don't apply any bad state to actor in case prone was set. Eventually, the return should be removed once prone is implemented properly
// DurationMs = 0;
// return;
// }
//
// ApplyMovementSettings(MoverComp);
// }
// }
// }
//
// void FGMS_MovementStateModifier::OnEnd(UMoverComponent* MoverComp, const FMoverTimeStep& TimeStep, const FMoverSyncState& SyncState, const FMoverAuxStateContext& AuxState)
// {
// const AActor* OwnerCDO = Cast<AActor>(MoverComp->GetOwner()->GetClass()->GetDefaultObject());
//
// if (UCapsuleComponent* CapsuleComponent = Cast<UCapsuleComponent>(MoverComp->GetUpdatedComponent()))
// {
// if (const UCapsuleComponent* OriginalCapsule = UMovementUtils::GetOriginalComponentType<UCapsuleComponent>(MoverComp->GetOwner()))
// {
// if (const APawn* OwnerCDOAsPawn = Cast<APawn>(OwnerCDO))
// {
// AdjustCapsule(MoverComp, CapsuleComponent->GetScaledCapsuleHalfHeight(), OriginalCapsule->GetScaledCapsuleHalfHeight(), OwnerCDOAsPawn->BaseEyeHeight);
// RevertMovementSettings(MoverComp);
// }
// }
// }
// }
//
// void FGMS_MovementStateModifier::OnPreMovement(UMoverComponent* MoverComp, const FMoverTimeStep& TimeStep)
// {
// // TODO: Check for different inputs/state here and manage swapping between stances - use AdjustCapsule and Apply/Revert movement settings.
//
// // TODO: Prone isn't currently implemented - so we're just going to cancel the modifier if we got into that state
// if (ActiveStance == EStanceMode::Prone)
// {
// UE_LOG(LogMover, Warning, TEXT("Stance got into prone stance - That stance is not currently implemented."));
// DurationMs = 0;
// }
// }
//
// void FGMS_MovementStateModifier::OnPostMovement(UMoverComponent* MoverComp, const FMoverTimeStep& TimeStep, const FMoverSyncState& SyncState, const FMoverAuxStateContext& AuxState)
// {
// FMovementModifierBase::OnPostMovement(MoverComp, TimeStep, SyncState, AuxState);
// }
//
// FMovementModifierBase* FGMS_MovementStateModifier::Clone() const
// {
// FGMS_MovementStateModifier* CopyPtr = new FGMS_MovementStateModifier(*this);
// return CopyPtr;
// }
//
// void FGMS_MovementStateModifier::NetSerialize(FArchive& Ar)
// {
// Super::NetSerialize(Ar);
// }
//
// UScriptStruct* FGMS_MovementStateModifier::GetScriptStruct() const
// {
// return StaticStruct();
// }
//
// FString FGMS_MovementStateModifier::ToSimpleString() const
// {
// return FString::Printf(TEXT("Stance Modifier"));
// }
//
// void FGMS_MovementStateModifier::AddReferencedObjects(FReferenceCollector& Collector)
// {
// Super::AddReferencedObjects(Collector);
// }
//
//
// void FGMS_MovementStateModifier::ApplyMovementSettings(UMoverComponent* MoverComp)
// {
// switch (ActiveStance)
// {
// default:
// case EStanceMode::Crouch:
// if (UStanceSettings* StanceSettings = MoverComp->FindSharedSettings_Mutable<UStanceSettings>())
// {
// // Update relevant movement settings
// if (UCommonLegacyMovementSettings* MovementSettings = MoverComp->FindSharedSettings_Mutable<UCommonLegacyMovementSettings>())
// {
// MovementSettings->Acceleration = StanceSettings->CrouchingMaxAcceleration;
// MovementSettings->MaxSpeed = StanceSettings->CrouchingMaxSpeed;
// }
// }
//
// break;
//
// // Prone isn't currently implemented properly so we're just doing nothing for now
// case EStanceMode::Prone:
// UE_LOG(LogMover, Warning, TEXT("Stance got into prone stance - That mode is not currently implemented fully."));
// break;
// }
// }
//
// void FGMS_MovementStateModifier::RevertMovementSettings(UMoverComponent* MoverComp)
// {
// if (const UMoverComponent* CDOMoverComp = UMovementUtils::GetOriginalComponentType<UMoverComponent>(MoverComp->GetOwner()))
// {
// const UCommonLegacyMovementSettings* OriginalMovementSettings = CDOMoverComp->FindSharedSettings<UCommonLegacyMovementSettings>();
// UCommonLegacyMovementSettings* MovementSettings = MoverComp->FindSharedSettings_Mutable<UCommonLegacyMovementSettings>();
//
// // Revert movement settings back to original settings
// if (MovementSettings && OriginalMovementSettings)
// {
// MovementSettings->Acceleration = OriginalMovementSettings->Acceleration;
// MovementSettings->MaxSpeed = OriginalMovementSettings->MaxSpeed;
// }
// }
// }

View File

@@ -0,0 +1,14 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/Walking/GMS_WalkingMode.h"
#include "Mover/GMS_MoverSettingObjectLibrary.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_WalkingMode)
UGMS_WalkingMode::UGMS_WalkingMode(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SharedSettingsClasses.Add(UGMS_MoverGroundedMovementSettings::StaticClass());
}

View File

@@ -0,0 +1,8 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/Zipline/GMS_ZiplineInterface.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_ZiplineInterface)
// Add default functionality here for any IGMS_ZiplineInterface functions that are not pure virtual.

View File

@@ -0,0 +1,93 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/Zipline/GMS_ZiplineModeTransition.h"
#include "GameFramework/Actor.h"
#include "DefaultMovementSet/CharacterMoverComponent.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Mover/GMS_MoverStructLibrary.h"
#include "Mover/Zipline/GMS_ZiplineInterface.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_ZiplineModeTransition)
// UGMS_ZiplineStartTransition //////////////////////////////
UGMS_ZiplineStartTransition::UGMS_ZiplineStartTransition(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
#if ENGINE_MINOR_VERSION >=6
FTransitionEvalResult UGMS_ZiplineStartTransition::Evaluate_Implementation(const FSimulationTickParams& Params) const
#else
FTransitionEvalResult UGMS_ZiplineStartTransition::OnEvaluate(const FSimulationTickParams& Params) const
#endif
{
FTransitionEvalResult EvalResult = FTransitionEvalResult::NoTransition;
UCharacterMoverComponent* MoverComp = Cast<UCharacterMoverComponent>(Params.MovingComps.MoverComponent.Get());
const FMoverSyncState& SyncState = Params.StartState.SyncState;
if (MoverComp && MoverComp->IsAirborne() && SyncState.MovementMode != ZipliningModeName)
{
if (const FGMS_MoverTagInputs* AbilityInputs = Params.StartState.InputCmd.InputCollection.FindDataByType<FGMS_MoverTagInputs>())
{
if (ZipliningInputTag.IsValid() && AbilityInputs->Tags.HasTagExact(ZipliningInputTag))
{
TArray<AActor*> OverlappingActors;
MoverComp->GetOwner()->GetOverlappingActors(OUT OverlappingActors);
for (AActor* CandidateActor : OverlappingActors)
{
bool bIsZipline = UKismetSystemLibrary::DoesImplementInterface(CandidateActor, UGMS_ZiplineInterface::StaticClass());
if (bIsZipline)
{
EvalResult.NextMode = ZipliningModeName;
break;
}
}
}
}
}
return EvalResult;
}
// UGMS_ZiplineEndTransition //////////////////////////////
UGMS_ZiplineEndTransition::UGMS_ZiplineEndTransition(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
#if ENGINE_MINOR_VERSION >=6
FTransitionEvalResult UGMS_ZiplineEndTransition::Evaluate_Implementation(const FSimulationTickParams& Params) const
#else
FTransitionEvalResult UGMS_ZiplineEndTransition::OnEvaluate(const FSimulationTickParams& Params) const
#endif
{
FTransitionEvalResult EvalResult = FTransitionEvalResult::NoTransition;
if (const FCharacterDefaultInputs* DefaultInputs = Params.StartState.InputCmd.InputCollection.FindDataByType<FCharacterDefaultInputs>())
{
if (DefaultInputs->bIsJumpJustPressed)
{
EvalResult.NextMode = AutoExitToMode;
}
}
return EvalResult;
}
#if ENGINE_MINOR_VERSION >=6
void UGMS_ZiplineEndTransition::Trigger_Implementation(const FSimulationTickParams& Params)
#else
void UGMS_ZiplineEndTransition::OnTrigger(const FSimulationTickParams& Params)
#endif
{
//TODO: create a small jump, using current directionality
}

View File

@@ -0,0 +1,243 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Mover/Zipline/GMS_ZipliningMode.h"
#include "MoverComponent.h"
#include "DefaultMovementSet/Settings/CommonLegacyMovementSettings.h"
#include "Kismet/KismetSystemLibrary.h"
#include "MoveLibrary/MovementUtils.h"
#include "Mover/Zipline/GMS_ZiplineInterface.h"
#include "Mover/Zipline/GMS_ZiplineModeTransition.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_ZipliningMode)
// FGMS_ZipliningState //////////////////////////////
FMoverDataStructBase* FGMS_ZipliningState::Clone() const
{
FGMS_ZipliningState* CopyPtr = new FGMS_ZipliningState(*this);
return CopyPtr;
}
bool FGMS_ZipliningState::NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess)
{
Super::NetSerialize(Ar, Map, bOutSuccess);
Ar << ZiplineActor;
Ar.SerializeBits(&bIsMovingAtoB, 1);
bOutSuccess = true;
return true;
}
void FGMS_ZipliningState::ToString(FAnsiStringBuilderBase& Out) const
{
Super::ToString(Out);
Out.Appendf("ZiplineActor: %s\n", *GetNameSafe(ZiplineActor));
Out.Appendf("IsMovingAtoB: %d\n", bIsMovingAtoB);
}
bool FGMS_ZipliningState::ShouldReconcile(const FMoverDataStructBase& AuthorityState) const
{
const FGMS_ZipliningState* AuthorityZiplineState = static_cast<const FGMS_ZipliningState*>(&AuthorityState);
return (ZiplineActor != AuthorityZiplineState->ZiplineActor) ||
(bIsMovingAtoB != AuthorityZiplineState->bIsMovingAtoB);
}
void FGMS_ZipliningState::Interpolate(const FMoverDataStructBase& From, const FMoverDataStructBase& To, float Pct)
{
const FGMS_ZipliningState* FromState = static_cast<const FGMS_ZipliningState*>(&From);
const FGMS_ZipliningState* ToState = static_cast<const FGMS_ZipliningState*>(&To);
ZiplineActor = ToState->ZiplineActor;
bIsMovingAtoB = ToState->bIsMovingAtoB;
}
// UGMS_ZipliningMode //////////////////////////////
UGMS_ZipliningMode::UGMS_ZipliningMode(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
Transitions.Add(CreateDefaultSubobject<UGMS_ZiplineEndTransition>(TEXT("ZiplineEndTransition")));
}
#if ENGINE_MINOR_VERSION >=6
void UGMS_ZipliningMode::GenerateMove_Implementation(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FProposedMove& OutProposedMove) const
#else
void UGMS_ZipliningMode::OnGenerateMove(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FProposedMove& OutProposedMove) const
#endif
{
UMoverComponent* MoverComp = GetMoverComponent();
// Ziplining is just following a path from A to B, so all movement is handled in OnSimulationTick
OutProposedMove = FProposedMove();
}
#if ENGINE_MINOR_VERSION >=6
void UGMS_ZipliningMode::SimulationTick_Implementation(const FSimulationTickParams& Params, FMoverTickEndData& OutputState)
#else
void UGMS_ZipliningMode::OnSimulationTick(const FSimulationTickParams& Params, FMoverTickEndData& OutputState)
#endif
{
// Are we continuing a move or starting fresh?
const FGMS_ZipliningState* StartingZipState = Params.StartState.SyncState.SyncStateCollection.FindDataByType<FGMS_ZipliningState>();
FMoverDefaultSyncState& OutputSyncState = OutputState.SyncState.SyncStateCollection.FindOrAddMutableDataByType<FMoverDefaultSyncState>();
FGMS_ZipliningState& OutZipState = OutputState.SyncState.SyncStateCollection.FindOrAddMutableDataByType<FGMS_ZipliningState>();
USceneComponent* UpdatedComponent = Params.MovingComps.UpdatedComponent.Get();
UMoverComponent* MoverComp = Params.MovingComps.MoverComponent.Get();
AActor* MoverActor = MoverComp->GetOwner();
USceneComponent* StartPoint = nullptr;
USceneComponent* EndPoint = nullptr;
FVector ZipDirection;
FVector FlatFacingDir;
const float DeltaSeconds = Params.TimeStep.StepMs * 0.001f;
FVector ActorOrigin;
FVector BoxExtent;
MoverActor->GetActorBounds(true, OUT ActorOrigin, OUT BoxExtent);
const FVector ActorToZiplineOffset = MoverComp->GetUpDirection() * BoxExtent.Z;
if (!StartingZipState)
{
// There is no existing zipline state... so let's find the target
// A) teleport to the closest starting point, set the zip direction
// B) choose the appropriate facing direction
// C) choose the appropriate initial velocity
TArray<AActor*> OverlappingActors;
MoverComp->GetOwner()->GetOverlappingActors(OUT OverlappingActors);
for (AActor* CandidateActor : OverlappingActors)
{
bool bIsZipline = UKismetSystemLibrary::DoesImplementInterface(CandidateActor, UGMS_ZiplineInterface::StaticClass());
if (bIsZipline)
{
const FVector MoverLoc = UpdatedComponent->GetComponentLocation();
USceneComponent* ZipPointA = IGMS_ZiplineInterface::Execute_GetStartComponent(CandidateActor);
USceneComponent* ZipPointB = IGMS_ZiplineInterface::Execute_GetEndComponent(CandidateActor);
if (FVector::DistSquared(ZipPointA->GetComponentLocation(), MoverLoc) < FVector::DistSquared(ZipPointB->GetComponentLocation(), MoverLoc))
{
OutZipState.bIsMovingAtoB = true;
StartPoint = ZipPointA;
EndPoint = ZipPointB;
}
else
{
OutZipState.bIsMovingAtoB = false;
StartPoint = ZipPointB;
EndPoint = ZipPointA;
}
ZipDirection = (EndPoint->GetComponentLocation() - StartPoint->GetComponentLocation()).GetSafeNormal();
const FVector WarpLocation = StartPoint->GetComponentLocation() - ActorToZiplineOffset;
FlatFacingDir = FVector::VectorPlaneProject(ZipDirection, MoverComp->GetUpDirection()).GetSafeNormal();
OutZipState.ZiplineActor = CandidateActor;
UpdatedComponent->GetOwner()->TeleportTo(WarpLocation, FlatFacingDir.ToOrientationRotator());
break;
}
}
// If we were unable to find a valid target zipline, refund all the time and let the actor fall
if (!StartPoint || !EndPoint)
{
FName DefaultAirMode = DefaultModeNames::Falling;
if (UCommonLegacyMovementSettings* LegacySettings = MoverComp->FindSharedSettings_Mutable<UCommonLegacyMovementSettings>())
{
DefaultAirMode = LegacySettings->AirMovementModeName;
}
OutputState.MovementEndState.NextModeName = DefaultModeNames::Falling;
OutputState.MovementEndState.RemainingMs = Params.TimeStep.StepMs;
return;
}
}
else
{
check(StartingZipState->ZiplineActor);
OutZipState = *StartingZipState;
USceneComponent* ZipPointA = IGMS_ZiplineInterface::Execute_GetStartComponent(StartingZipState->ZiplineActor);
USceneComponent* ZipPointB = IGMS_ZiplineInterface::Execute_GetEndComponent(StartingZipState->ZiplineActor);
if (StartingZipState->bIsMovingAtoB)
{
StartPoint = ZipPointA;
EndPoint = ZipPointB;
}
else
{
StartPoint = ZipPointB;
EndPoint = ZipPointA;
}
ZipDirection = (EndPoint->GetComponentLocation() - StartPoint->GetComponentLocation()).GetSafeNormal();
FlatFacingDir = FVector::VectorPlaneProject(ZipDirection, MoverComp->GetUpDirection()).GetSafeNormal();
}
// Now let's slide along the zipline
const FVector StepStartPos = UpdatedComponent->GetComponentLocation() + ActorToZiplineOffset;
const FVector DesiredEndPos = StepStartPos + (ZipDirection * MaxSpeed * DeltaSeconds); // TODO: Make speed more dynamic
FVector ActualEndPos = FMath::ClosestPointOnSegment(DesiredEndPos,
StartPoint->GetComponentLocation(),
EndPoint->GetComponentLocation());
bool bWillReachEndPosition = (ActualEndPos - EndPoint->GetComponentLocation()).IsNearlyZero();
FVector MoveDelta = ActualEndPos - StepStartPos;
FMovementRecord MoveRecord;
MoveRecord.SetDeltaSeconds(DeltaSeconds);
if (!MoveDelta.IsNearlyZero())
{
FHitResult Hit(1.f);
UMovementUtils::TrySafeMoveUpdatedComponent(Params.MovingComps, MoveDelta, FlatFacingDir.ToOrientationQuat(), true, Hit, ETeleportType::None, MoveRecord);
}
const FVector FinalLocation = UpdatedComponent->GetComponentLocation();
const FVector FinalVelocity = MoveRecord.GetRelevantVelocity();
OutputSyncState.SetTransforms_WorldSpace(FinalLocation,
UpdatedComponent->GetComponentRotation(),
FinalVelocity,
nullptr); // no movement base
UpdatedComponent->ComponentVelocity = FinalVelocity;
if (bWillReachEndPosition)
{
FName DefaultAirMode = DefaultModeNames::Falling;
if (UCommonLegacyMovementSettings* LegacySettings = MoverComp->FindSharedSettings_Mutable<UCommonLegacyMovementSettings>())
{
DefaultAirMode = LegacySettings->AirMovementModeName;
}
OutputState.MovementEndState.NextModeName = DefaultAirMode;
// TODO: If we reach the end position early, we should refund the remaining time
}
}