106 lines
3.8 KiB
C++
106 lines
3.8 KiB
C++
#include "GameplayModes/PwnGameplayModeSubsystem.h"
|
|
|
|
#include "Components/SplineComponent.h"
|
|
#include "GameplayModes/Combat/PwnCombatPlatformerPath.h"
|
|
#include "Utils/EngineUtils.h"
|
|
|
|
UPwnGameplayModeSubsystem& UPwnGameplayModeSubsystem::Get(const UObject* WorldContextObject) {
|
|
const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject);
|
|
UPwnGameplayModeSubsystem* GameplayModeSubsystem = World->GetSubsystem<UPwnGameplayModeSubsystem>();
|
|
check(GameplayModeSubsystem);
|
|
return *GameplayModeSubsystem;
|
|
}
|
|
|
|
void UPwnGameplayModeSubsystem::Initialize(FSubsystemCollectionBase& Collection) {
|
|
Super::Initialize(Collection);
|
|
CurrentGameplayMode = EPwnGameplayMode::Narrative;
|
|
}
|
|
|
|
void UPwnGameplayModeSubsystem::Deinitialize() {
|
|
Super::Deinitialize();
|
|
}
|
|
|
|
void UPwnGameplayModeSubsystem::SetGameplayMode(EPwnGameplayMode GameplayMode) {
|
|
if (GameplayMode != CurrentGameplayMode) {
|
|
CurrentGameplayMode = GameplayMode;
|
|
if (OnGameplayModeChanged.IsBound()) {
|
|
OnGameplayModeChanged.Broadcast(CurrentGameplayMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
EPwnGameplayMode UPwnGameplayModeSubsystem::GetCurrentGameplayMode() const {
|
|
return CurrentGameplayMode;
|
|
}
|
|
|
|
bool UPwnGameplayModeSubsystem::IsNarrativeMode() const {
|
|
return CurrentGameplayMode == EPwnGameplayMode::Narrative;
|
|
}
|
|
|
|
bool UPwnGameplayModeSubsystem::IsCombatMode() const {
|
|
return CurrentGameplayMode == EPwnGameplayMode::Combat;
|
|
}
|
|
|
|
void UPwnGameplayModeSubsystem::RegisterCombatPath(APwnCombatPlatformerPath* CombatPath) {
|
|
CombatPaths.Add(CombatPath);
|
|
}
|
|
|
|
void UPwnGameplayModeSubsystem::UnregisterCombatPath(APwnCombatPlatformerPath* CombatPath) {
|
|
CombatPaths.Remove(CombatPath);
|
|
}
|
|
|
|
bool UPwnGameplayModeSubsystem::FindClosestCombatPathLocation(const FVector& Location, APwnCombatPlatformerPath*& OutCombatPath, FVector& ClosestLocation) const {
|
|
float BestDistanceAlongTheSpline = -1;
|
|
float ShortestZOffset = FLT_MAX;
|
|
APwnCombatPlatformerPath* ClosestCombatPath = nullptr;
|
|
|
|
const FVector Location2D = FVector(Location.X, Location.Y, 0.0f);
|
|
|
|
for (APwnCombatPlatformerPath* CombatPath : CombatPaths) {
|
|
const USplineComponent* CurrentSpline = CombatPath->Spline;
|
|
CombatPath->UpdateFlattenSpline(CombatPath->Spline->FindInputKeyClosestToWorldLocation(Location));
|
|
|
|
const FVector FlattenedLocation = CombatPath->FlattenedSpline->FindLocationClosestToWorldLocation(Location, ESplineCoordinateSpace::World);
|
|
|
|
const float CurrentKey = CurrentSpline->FindInputKeyClosestToWorldLocation(FlattenedLocation);
|
|
const float CurrentDistance = CurrentSpline->GetDistanceAlongSplineAtSplineInputKey(CurrentKey);
|
|
|
|
float BestDistance = -1;
|
|
float ShortestDistanceForThisPath = FLT_MAX;
|
|
|
|
for (int i = -700; i <= 700; i += 5) {
|
|
const float SubStepDistance = CurrentDistance + i;
|
|
const FVector SubStepLocation = CurrentSpline->GetLocationAtDistanceAlongSpline(SubStepDistance, ESplineCoordinateSpace::World);
|
|
if (SubStepLocation.Z < Location.Z) {
|
|
continue;
|
|
}
|
|
FVector SubStepLocation2D = FVector(SubStepLocation.X, SubStepLocation.Y, 0.0f);
|
|
const float Distance = FVector::DistSquared(Location2D, SubStepLocation2D);
|
|
if (Distance < ShortestDistanceForThisPath) {
|
|
ShortestDistanceForThisPath = Distance;
|
|
BestDistance = SubStepDistance;
|
|
}
|
|
}
|
|
|
|
if (BestDistance < 0) {
|
|
continue;
|
|
}
|
|
|
|
const FVector BestLocation = CurrentSpline->GetLocationAtDistanceAlongSpline(BestDistance, ESplineCoordinateSpace::World);
|
|
|
|
const float ZOffset = BestLocation.Z - Location.Z;
|
|
if (ZOffset < ShortestZOffset) {
|
|
ClosestCombatPath = CombatPath;
|
|
BestDistanceAlongTheSpline = BestDistance;
|
|
ShortestZOffset = ZOffset;
|
|
}
|
|
}
|
|
|
|
if (ClosestCombatPath != nullptr) {
|
|
OutCombatPath = ClosestCombatPath;
|
|
ClosestLocation = OutCombatPath->Spline->GetLocationAtDistanceAlongSpline(BestDistanceAlongTheSpline, ESplineCoordinateSpace::World);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|